一.Iterator接口

java.util.Iterator接口也是Java集合中的一员,只是它主要用于迭代访问集合中的元素,也就是遍历数据,而Collection和Map接口是用来存储数据。

Iterator接口也被称为迭代器,迭代器遍历的过程不能进行元素的增删操作。

增强for循环的内部原理使用的就是Iterator迭代器。

Iterator接口提供了以下几个常用方法:

  • public E next():返回迭代中的下一个元素
  • public boolean hasNext():如果迭代器还有元素,返回true

而Collection集合中提供了获取迭代器的方法:

public Iterator iterator():获取集合对应的迭代器,用来遍历集合的元素。

public class IteratorDemo {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();

        list.add(5);
        list.add(3);
        list.add(2);
        list.add(4);
        list.add(1);

        // 获取迭代器Iterator
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

二.集合工具类Collections

注意这里的是Collections,比起集合Collection多了一个字母s,是一个集合工具类,提供了一些方法方便对集合进行操作。

常用的方法如下:

  • public static <T> boolean addAll(Collection<T> c, T... elements):将所有指定的元素添加到指定的集合中。
  • public static void shuffle(List<?> list):随机打乱集合顺序
  • public static <T> void sort(List<T> list):将集合中的元素按默认排序规则排序(升序)
  • public static <T> void sort(List<T> list, Comparator<? super T> c):将集合中的元素按照指定规则进行排序
public class CollectionsDemo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        // 以前添加元素方式
//        list.add(1);
//        list.add(2);
//        list.add(3);
//        list.add(4);
//        list.add(5);

        // 使用Collections添加元素到list
        Collections.addAll(list, 1,2,3,4,5);
        System.out.println(list); // 输出:[1, 2, 3, 4, 5]

        // 随机打乱集合元素顺序
        Collections.shuffle(list);
        System.out.println(list); // 输出:[1, 3, 4, 5, 2]

        // 使用默认的排序规则排列list
        Collections.sort(list);
        System.out.println(list); // 输出:[1, 2, 3, 4, 5]
    }
}

对于另一个排序方法:sort(List<T> list, Comparator<? super T> c),允许我们实现Comparator接口来自定义排序规则。

在java中提供了两种比较的实现方式:

  1. java.langComparable接口实现
    如果一个类实现了Comparable,则意味着这个类支持排序,则可以通过Collections.sort或者Arrays.sort进行排序。
    Comparable接口内部只有一个方法public int compareTo(T o),能够让实现Comparable接口的类对象进行比较,具体的比较规则是:
e1.compareTo(e2) > 0 则 e1 > e2
e1.compareTo(e2) = 0 则 e1 = e2
e1.compareTo(e2) < 0 则 e1 < e2

排列顺序其实主要是看-1,-1决定其是否要调整顺序: if(o1.compareTo(o2) < 0 ){ return ?; } //这里o1表示位于前面的字符,o2表示后面的字符 //上面的条件是,o1比o2小,这个时候,我们需要需要调整它们的顺序 //如果你想升序,那么o1比o2小就是我想要的;所以返回-1,类比成false;表示我不想调整顺序 //如果你想降序,那么o1比o2小不是我想要的;所以返回1,类比成true;表示我想调整顺序

记忆:

如果return e1 - e2; 默认为升序排序
如果return e2 - e1; 默认为降序排序


比如在类中实现Comparable接口,实现compareTo()方法:

@Override
public int compareTo(Person person) {
    return this.age - person.age; // 升序
}
  1. java.util.Comparator接口实现
    Comparator是比较器接口,可以将Comparator传递给sort方法,从而控制排序,也可以为那些没有实现排序的对象提供排序。
    Comparator接口提供了一个比较方法:public int compare(T o1, T o2):比较两个参数的顺序

两个对象比较的结果有三种:大于,等于,小于,对于compare函数,是根据返回值来比较的。

记忆方式和比较方式和Comparable一样,可以看上面。

如果return o1 - o2; 默认为升序排序
如果return o2 - o1; 默认为降序排序
  1. 两者的区别
    Comparable是自然排序,由实体类实现
    Comparator是定制排序,无法修改实体类的实现时,直接在调用方创建
    两者都存在时,采用Comparator的规则进行比较排序。
    可以看出,Comparable相当于是内部的比较器,而Comparator则相当于是外部的比较器。
  2. 排序的练习
    需求:对自定义类,存储到List集合中完成相关排序操作。
    先实现自定义类:
package com.zzy.www.ListDemo;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
    @Override
    public int compareTo(Person person) {
        return this.age - person.age; // 升序
    }
}

如果想要集合的元素进行排序,那么Person必须要实现Comparable接口,才可排序,因此需要给Person类添加实现接口Comparable。

编写一个测试类:

public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();

        // 添加元素
        list.add(new Person("张三", 38));
        list.add(new Person("李四", 25));
        list.add(new Person("王五",20));
        list.add(new Person("赵六", 18));

        // 按年龄升序排序
        Collections.sort(list);

        // 遍历
        for (Person p : list) {
            System.out.println(p);
        }
        // 输出内容:
        /*
        Person{name='赵六', age=18}
        Person{name='王五', age=20}
        Person{name='李四', age=25}
        Person{name='张三', age=38}
        */
    }
}

以上的实现方式,对于存储Person对象的集合排序就只能用升序的方式排列了,如果想要使用其他规则去排序,显然改变Person中compareTo方法并不是一个好的方式,这是就可以使用Collections.sort方法实现Comparator接口,自己定义排序规则。

修改测试类:

public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();

        // 添加元素
        list.add(new Person("张三", 38));
        list.add(new Person("李四", 25));
        list.add(new Person("王五",20));
        list.add(new Person("赵六", 18));

        // 按年龄升序排序
//        Collections.sort(list);

        // 按年龄降序排序
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person person, Person t1) {
                return t1.getAge() - person.getAge();
            }
        });
        
        // 遍历
        for (Person p : list) {
            System.out.println(p);
        }
        /*输出:
        Person{name='张三', age=38}
        Person{name='李四', age=25}
        Person{name='王五', age=20}
        Person{name='赵六', age=18}*/
    }
}

除了升序降序,如果还想要其他排序规则,都可以通过Collections.sort去定义,比如如下:

先按年龄降序排序,如果年龄一致,则按照姓名的首字母升序排序。

public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();

        // 添加元素
        list.add(new Person("zhangsan", 38));
        list.add(new Person("lisi", 38));
        list.add(new Person("wangwu",20));
        list.add(new Person("zhaoliu", 18));

        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person person, Person t1) {
                int ret = person.getAge() - t1.getAge();
                if (ret == 0) {
                    ret = person.getName().charAt(0) - t1.getName().charAt(0);
                }
                return ret;
            }
        });

        // 遍历
        for (Person p : list) {
            System.out.println(p);
        }
        /*输出:
        Person{name='zhaoliu', age=18}
        Person{name='wangwu', age=20}
        Person{name='lisi', age=38}
        Person{name='zhangsan', age=38}*/
    }
}