Collections中的sort()方法、compareTo()方法、max()方法、min()方法

2023-05-16

sort是进行collection集合进行排序使用的方法。会自动调用compareTo()方法,对集合进行排序。

一般步骤:

要排序的类要实现Comparable<?>接口,然后重写compareTo()方法;最后再调用sort(Collection)方法。调用sort()方法以后,sort()方法会自动调用compareTo()方法。

sort源码:实力尚浅,暂不分析。

代码:

public class CollectionTest1 implements Comparable<CollectionTest1>{

    private String name;
    private Integer age;
    private String gender;

    public CollectionTest1() {

    }

    public CollectionTest1(String name, Integer age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "CollectionTest1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    @Override
    public int compareTo(CollectionTest1 person) {

        if (person.age>this.age){
            return 1;
        }else if (person.age==this.age){
            return 0;
        }else {
            return -1;
        }
    }

    public static void main(String[] args) {
        List<CollectionTest1> list = new ArrayList<>();
        list.add(new CollectionTest1("张三",20,"男"));
        list.add(new CollectionTest1("李四",24,"男"));
        list.add(new CollectionTest1("王五",23,"女"));
        list.add(new CollectionTest1("赵六",26,"男"));
        list.add(new CollectionTest1("孙七",18,"女"));
        list.add(new CollectionTest1("周八",18,"女"));


        System.out.println("排序前:");
        for (CollectionTest1 collectionTest1 : list) {
            System.out.println(collectionTest1.toString());
        }
        Collections.sort(list);
        System.out.println("排序后:-----------------------------------------");
        for (CollectionTest1 collectionTest1 : list) {
            System.out.println(collectionTest1.toString());
        }

说明:

实现Comparable<T>接口之后,compareTo()方法必须要被重写,增加业务逻辑。

浅析compareTo()方法:

(本人目前是个初学者,看不太明白源码,只能是自话自说,如与事实不符,敬请在评论区斧正!)

一般compareTo()方法中,进行排序的业务代码都是返回1,0,-1。其中this代指即将传入的对象,然后.出可比较的属性。

返回1就代表 要比较的元素在被比较元素  的后面,继续向后比较;

返回-1就代表 要比较的元素在被比较元素  的前面,不再继续向后比较;

返回0就代表 要比较的元素和被比较元素 相等,先来后到,放在被比较数的后面,不再向后比较;

用目前的眼光看来,比较时与List集合中的元素逐个比较(一开始是空的),比较后的数据按顺序放在此List集合中。

规则:

this.属性>集合传入对象.属性,返回1;

this.属性==集合传入对象.属性,返回0;

this.属性<集合传入对象.属性,返回-1。

这样排的顺序是从小到大排列;

反过来:

this.属性<集合传入对象.属性,返回1;

this.属性==集合传入对象.属性,返回0;

this.属性>集合传入对象.属性,返回-1。

这样的排序是从大到小排列。

下面为个人理解:

在重写compareTo()方法时,传入的对象规定List集合的类型,初始化为空List对象集合。等比较的时候,将传入的属性值与List集合中的元素对应属性值进行逐个比较,以此来确定将要存放的位置。所以速度较慢。

以上述代码中例子为例:根据年龄age排序

第一次比较:this.age是20,person.age是List<CollectionTest1>中取出的元素对象属性值,一开始没有数据,所以为null,看作0。this.age>person.age,返回1,现在的List集合中[20];

第二次比较:this.age是24,person.age是20,this.age>person.age,返回-1,现在List集合中[24,20];

第三次比较:this.age是23,第一个person.age是24,this.age<person.age,返回1;第二个person.age是20,this.age>person.age,返回-1。现在List集合中[24,23,20];

第四次比较:this.age是26,第一个person.age是24,this.age>person.age,返回-1;现在List集合中[26,24,23,20];

第五次比较:this.age是18,第一个person.age是26,this.age<person.age,返回1,继续比较;

                                             第二个person.age是24,this.age<person.age,返回1,继续比较;

                                             第三个person.age是23,this.age<person.age,返回1,继续比较;

                                             第四个person.age是20,this.age<person.age,返回1,继续比较;

                这时候List集合已经没有可以比较的元素了,所以 

                              第五个person.age是null,看作0,this.age>person.age,返回-1,停止比较;

现在List集合中[26,24,23,20,18];

第六次比较,this.age是18,第一个person.age是26,this.age<person.age,返回1,继续比较;

                                             第二个person.age是24,this.age<person.age,返回1,继续比较;

                                             第三个person.age是23,this.age<person.age,返回1,继续比较;

                                             第四个person.age是20,this.age<person.age,返回1,继续比较;

 第五个person.age是18,this.age==person.age,返回0,直接放在被比较数的后面,停止比较;

现在List集合中[26,24,23,20,18,18];

所以排序后,遍历结果是    26,24,23,20,18,18   对应的元素对象。

max和min:

源码:

---------------------max----------------------------

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) > 0)
                candidate = next;
        }
        return candidate;
    }




-------------------min----------------------------

public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) < 0)
                candidate = next;
        }
        return candidate;
    }

Collections中的max()和min()方法根据compareTo()中的规则进行判断取值规则写反,就取反。

为何写反取反?因为源码中判断是这样的:根据返回值来判断,然后赋值。

比如max方法中

先是定义迭代器Iterator迭代集合元素,然后定义一个变量candidate,接收next()指针指向的当前元素。

紧接着开始使用while遍历集合,新定义一个变量next,将指针指向的当前元素赋值给它。

然后使用我们重写的compareTo()方法进行if条件分支判断注意,这里是next在前,candidate在后进行比较。若后一个元素与前一个元素的compareTo()方法返回的值是1,证明前一个元素大于后一个元素,而1>0为true,则将后一个元素next的值赋给前一个元素candidate。若为false则不赋值。然后直到遍历完成,返回candidate。

min方法同理。写反取反

所以会出现下面的结果:

年龄最大:CollectionTest1{name='周八', age=18, gender='女'}
年龄最小:CollectionTest1{name='赵六', age=26, gender='男'}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Collections中的sort()方法、compareTo()方法、max()方法、min()方法 的相关文章

  • 如何在无 null 设计中实现 List、Set 和 Map?

    当您在大多数情况下可以返回 null 空对象以避免 null 时 这很好 但是像 Collection 这样的对象呢 在爪哇 Map回报null if key in get key 地图上没有找到 我能想到的最好的避免方法null在这种情况
  • 如何使用 Rally 的 JAVA API 将标签添加到 Rally 中的测试用例?

    我一直在努力向 Rally 中的测试用例添加标签 该标签已存在于 Tags 集合中 但我无法将其添加到测试用例中 有人可以提供一个关于如何执行此操作的示例吗 多谢 下面是如何执行此操作的示例 该示例显示了向现有测试用例添加标签 以及创建新测
  • Scala:获取 Map.head 元素的键(和值)

    让我们想象一下以下不可变的 Map val foo Map 10 ten 100 one hundred 我想获得第一个元素的密钥 foo head获取第一个元素 但接下来呢 我还想要这个元素的值 即 十 设置键 值对 val key va
  • Oracle 12 对 SQL 中的本地集合类型有问题吗?

    长话短说 我建议讨论下面看到的代码 运行时 Oracle 11 编译器引发 PLS 00306 调用 PIPE TABLE 时参数提示的数量或类型错误 PLS 00642 SQL 语句中不允许使用本地集合类型 Oracle 12编译下面的包
  • opencv形态扩张滤波器作为最大滤波器

    就像中值滤波器的定义一样 我可以将 最大滤波器 定义为局部窗口 例如dst x y max 3x3 局部窗口像素 但我在opencv中找不到这样的过滤器 最接近的是 dilate 函数 然后我使用 dilate 函数的默认配置 但结果不正确
  • 使用 Linq 返回具有最大计数的列表

    使用 C 和 Linq 如何返回具有最大大小 计数的 List 我假设您有一个名为的列表集合lists并且您想要返回此集合中元素最多的列表 如果是这样 请尝试以下操作 var listWithLargestCount lists Order
  • 避免集合已修改错误

    Issue 我有以下代码 foreach var ItemA in GenericListInstanceB ItemA MethodThatCouldRemoveAnyItemInGenericListInstanceB 显然我得到一个错
  • 将集合绑定到自定义控件属性

    我没有运气尝试将数据集合绑定到我的自定义控件的属性 我已经实现了该控件的字符串属性的机制 在此处提供了一些帮助 并期望集合类型同样简单 但是我无法让它再次工作 这是我的自定义控件视图
  • 如何检查某个元素是否存在于一组项目中?

    In an ifJava中的语句如何检查一个对象是否存在于一组项目中 例如 在这种情况下 我需要验证水果是苹果 橙子还是香蕉 if fruitname in APPLE ORANGES GRAPES Do something 这是一件非常微
  • C++ 中的 min= 习惯用法?

    We use x y 代替 x x y 同样对于 和其他运营商 嗯 那又怎样呢 x min y 代替 x std min x y 该命令是否有一个常用的习惯用法 不需要使用另一个运算符对语言进行 不可能的 扩展 这当然不是惯用的 但你也许可
  • codeigniter,获取mysql表列中的最大值

    我正在使用 codeigniter 2 我有一个 mysql 表列 存储每个学生所用的时间 例如 1 2327 0 6547 1 9876 我想获得最大值 值该列 这是我的代码 this gt db gt select max time t
  • 为什么应该首选 Java 类的接口?

    PMD https pmd github io 将举报以下违规行为 ArrayList list new ArrayList 违规行为是 避免使用 ArrayList 等实现类型 而是使用接口 以下行将纠正违规行为 List list ne
  • 为什么Iterator接口没有add方法

    In IteratorSun 添加了remove 方法来删 除集合中最后访问的元素 为什么没有add方法来向集合中添加新元素 它可能对集合或迭代器产生什么样的副作用 好的 我们开始吧 设计常见问题解答中明确给出了答案 为什么不提供 Iter
  • Java:从集合中获取第一项

    如果我有一个集合 例如Collection
  • 寻找基于循环固定大小数组的双端队列

    我正在寻找一个Deque其具有以下特点 它有固定的大小 如果我在头 尾添加元素 则另一端的元素会丢失 它是基于数组的 所以我可以在恒定时间内访问随机元素 我可以在前面或末尾添加元素 双端队列 我检查了Deque的实施JCF但我没有找到任何合
  • 添加到 HashMap 中的列表的快捷方式

    我经常需要获取一个对象列表 并根据对象中包含的值将它们分组到一个 Map 中 例如 按国家 地区获取用户和组列表 我的代码通常如下所示 Map
  • 为什么不能收集一定范围的字符?

    我正在尝试生成一个包含小写 ASCII 字符的向量 这种更复杂的方法有效 let ascii lowercase b a b z map b b as char collect
  • Java 使用函子连接集合

    给定 2 个具有相同数量元素的集合 例如List
  • 对对象集合进行排序[重复]

    这个问题在这里已经有答案了 如果我有一个简单的字符串列表 List
  • 频繁插入已排序的集合

    我已经对集合 列表 进行了排序 并且我需要始终保持其排序 我目前在我的集合上使用 List BinarySearch 然后在正确的位置插入元素 我也尝试过在每次插入后对列表进行排序 但性能不可接受 有没有一种解决方案可以提供更好的性能 也许

随机推荐