集合框架拓展


  • 迭代器Iterator
Iterator是java中的?个接?,核?作?就是?来遍历容器的元素,当容器实现了Iterator接?后,可以通过调?Iterator()?法获取?个 Iterator对象

由于容器的实现有多种,不同的容器遍历规则不?样,?如ArrayList/LinkedList/HashSet/TreeSet等,所以设计了Iterator接?,让容器本身去实现这个接?,实现??的?法,从?让开发?员不?关系容器的遍历机制,直接使?对应的?法即可

三个核??法:
    boolean hashNext()
    ?于判断iterator内是否有下个元素,如果有则返回true,没有则false
    Obejct next()
    返回iterator的下?个元素,同时指针也会向后移动1位
    void remove()
    删除指针的上?个元素
    只有当next执?完后,才能调?remove函数
    如要删除第?个元素,不能直接调? remove(),要先next?下()否则调?remove?法是会抛出异常的
  • 代码案例
# 迭代set集合
public static void testSet(){
   Set set = new HashSet<>();
   set.add("jack");
   set.add("tom");
   set.add("marry");
   set.add("tony");
   set.add("jack");

   Iterator iterator = set.iterator();
   while (iterator.hasNext()){
       String str = iterator.next();
       System.out.println(str);
   }
}

# 迭代list集合
 public static void testList(){
   List list = new ArrayList<>();
   list.add("jack");
   list.add("tom");
   list.add("mary");
   list.add("tim");
   list.add("tony");
   list.add("eric");
   list.add("jack");

   Iterator iterator = list.iterator();
   while (iterator.hasNext()){
       String str = iterator.next();
       System.out.println(str);
   }
}

# 迭代map集合
    public static  void testMap(){
        Map map = new HashMap<>();
        map.put("jack","广东");
        map.put("tim","广西");
        map.put("marry","海南");
       Set> entrySet = map.entrySet();
       Iterator> iterator = entrySet.iterator();
       while (iterator.hasNext()){
           Map.Entry entry = iterator.next();
             String str =  entry.getKey() +" = " + entry.getValue();
             System.out.println(str);
       }
    }
  • 迭代器注意事项
# 如下在迭代过程中直接使用list集合的remove方法删除元素,报错
public static void testList(){
 List list = new ArrayList<>();
 list.add("jack");
 list.add("tom");
 list.add("mary");
 list.add("tim");
 list.add("tony");
 list.add("eric");
 list.add("jack");
 Iterator iterator = list.iterator();
 while (iterator.hasNext()){
     String str = iterator.next();
     if("jack".equals(str)){
         list.remove(str);//ConcurrentModificationException并发修改异常
     }
     System.out.println(str);
     }
 }

# 如下在迭代的过程中使用list集合的方法删除1个元素后,跳出循环,不会报错
public static void testList(){
 List list = new ArrayList<>();
 list.add("jack");
 list.add("tom");
 list.add("mary");
 list.add("tim");
 list.add("tony");
 list.add("eric");
 list.add("jack");
 Iterator iterator = list.iterator();
 while (iterator.hasNext()){
     String str = iterator.next();
     if("jack".equals(str)){
         list.remove(str);
         break;
     }
     System.out.println(str);
     }
 }

# 如下在迭代的过程中,使用迭代器自己的remove方法删除元素,不会报错
public static void testList(){
 List list = new ArrayList<>();
 list.add("jack");
 list.add("tom");
 list.add("mary");
 list.add("tim");
 list.add("tony");
 list.add("eric");
 list.add("jack");
 Iterator iterator = list.iterator();
 while (iterator.hasNext()){
     String str = iterator.next();
     if("jack".equals(str)){
         iterator.remove(str);
     }
     System.out.println(str);
     }
 }
  • 升序排序
List list = new ArrayList<>();
list.add("aaaa");
list.add("zzz");
list.add("gggg");
Collections.sort(list);
System.out.println(list);
  • 降序排序
List list = new ArrayList<>();
list.add("aaaa");
list.add("zzz");
list.add("gggg");

//默认升序
Collections.sort(list, Comparator.naturalOrder());
System.out.println(list);

//降序
Collections.sort(list, Comparator.reverseOrder());
System.out.println(list);
  • 随机排序
List list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");

Collections.shuffle(list);
System.out.println(list);
  • 获取最大值或最小值
public class CollectionsTest {
   public static void main(String[] args) {
       List list = new ArrayList<>();
       list.add(new Student("jack", 26));
       list.add(new Student("tom", 29));
       list.add(new Student("mary", 32));
       list.add(new Student("tony", 19));
       list.add(new Student("smith", 41));

       # 返回值大于0,获取最大值
       Student maxAgeStudent = Collections.max(list, new Comparator() {
           @Override
           public int compare(Student o1, Student o2) {
               return o1.getAge() - o2.getAge();
           }
       });

       # 获取最大值,写法2
       Student maxAgeStudent = Collections.max(list, new StudentComparator());
       
       # 返回值小于0,获取最小值
       Student minAgeStudent = Collections.mix(list, new Comparator() {
           @Override
           public int compare(Student o1, Student o2) {
               return o1.getAge() - o2.getAge();
           }
       });

       System.out.println(maxAgeStudent.toString());
       System.out.println(minAgeStudent.toString());
   }
}

# 编写外部类实现Comparator,重写方法
public class StudentComparator implements Comparator {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge() - o2.getAge();
    }
}

# 实体类
class Student {

   private int age;
   private String name;

   public void setAge(int age) {
       this.age = age;
   }
   public int getAge() {
       return age;
   }
   public void setName(String name) {
       this.name = name;
   }
   public String getName() {
       return name;
   }

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

   @Override
   public String toString() {
       return "Student{" +
       "age=" + age +
       ", name='" + name + '\'' +
       '}';
   }
}
  • 创建不可变集合
List list = new ArrayList<>();
list.add("SpringBoot课程");
list.add("架构课程");
list.add("微服务SpringCloud课程"); 
list = Collections.unmodifiableList(list);    //设置为只读List集合
System.out.println(list);

Set set = new HashSet<>();
set.add("Mysql教程");
set.add("Linux服务器器教程");
set.add("Git教程");
set = Collections.unmodifiableSet(set);    //设置为只读Set集合
System.out.println(set);

Map map = new HashMap<>();
map.put("key1", "课程1");
map.put("key2", "课程2");
map = Collections.unmodifiableMap(map);    //设置为只读Map集合
System.out.println(map);
  • Comparable接口
是?个接?,定制排序规则
对实现它的每个类的对象进?整体排序,?? compareTo ?法是实现排序的具体?法
?如TreeSet、SortedSet、Collections.sort() ?法调?进?排序
String、Integer等类默认实现了这个接?,所以可以排序(看源码)

?于?较次对象和指定对象的顺序,o为要?较的对象
返回int类型
    ?于0, 表示this?于传进来的对象o ,则往后排,即升序
    等于0,表示this等于传进来的对象o
    ?于0,表示this?于传进来的对象o
  • Comparable代码案例
public class TestCom {
    public static void main(String [] args) {
        // set集合排序
        Set studentSet = new TreeSet<>();
        studentSet.add(new Student("jack",32));
        studentSet.add(new Student("tom",22));
        studentSet.add(new Student("mary",35));
        studentSet.add(new Student("tim",11));
        studentSet.add(new Student("tony",49));
        studentSet.add(new Student("dd",30));
        System.out.println(studentSet);

        // list集合排序
        List studentList = new ArrayList<>();
        studentList.add(new Student("jack",32));
        studentList.add(new Student("tom",22));
        studentList.add(new Student("mary",35));
        studentList.add(new Student("tim",11));
        studentList.add(new Student("tony",49));
        studentList.add(new Student("dd",30));
        Collections.sort(studentList);
        System.out.println(studentList);
    }
}

// 实体类实现Comparable
class Student implements Comparable{
    private int age;

    private String name;

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

    public int getAge() {
        return age;
    }


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

    public String getName() {
        return name;
    }

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

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

    // 重写compareTo方法
    @Override
    public int compareTo(Object o) {
        Student student = (Student) o;
        return this.age - student.age;
    }
}
  • Objects?具类
equals
    ?于字符串和包装对象的?较,先?较内存地址,再?较值
deepEquals
    数组的?较,先?较内存地址,再?较值,如String/char/byte/int数组, 或者包装类型Integer等数组
hashCode
    返回对象的hashCode,若传?的为null,返回0
hash
    传?可变参数的所有值的hashCode的总和,底层调?Arrays.hashCode
  • 代码案例
public class ObjectsTest {

    public static void main(String [] args){
        String str1 = "javase xdclass";
        String str2 = "javase xdclass";
        System.out.println(Objects.equals(str1,str2));
        
        String [] arr1 = {"aa","bb","cc"};
        String [] arr2 = {"aa","bb","cc"};
        System.out.println(Objects.deepEquals(arr1,arr2));

        System.out.println(Objects.hashCode("xdclass.net"));
        System.out.println(Objects.hashCode("xdclass.net."));
        System.out.println(Objects.hashCode("xdclassnet"));
        
        System.out.println(Objects.hash("xdclass",12,33L));
    }
}

// 可变参数只能放在最后1个参数位置,如下
public static int hash(int a, Object... values) {
   return Arrays.hashCode(values);
}
  • 重写HashCode?法
# 案例1,没有重写时
public class NativeMethodTest {
    public static void main(String [] args){
        Set userSet = new HashSet<>();
        userSet.add(new User("jack",22));
        userSet.add(new User("tom",12));
        userSet.add(new User("tony",22));
        userSet.add(new User("tom",12));
        System.out.println("userSet" + userSet);
    }
}

class User{

    private int age;

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

# 控制台,没有去重
userSet[User{age=12, name='tom'}, User{age=12, name='tom'}, User{age=22, name='jack'}, User{age=22, name='tony'}]

# 案例2,手动重写equals和hashCode方法
public class NativeMethodTest {
    public static void main(String [] args){
        Set userSet = new HashSet<>();
        userSet.add(new User("jack",22));
        userSet.add(new User("tom",12));
        userSet.add(new User("tony",22));
        userSet.add(new User("tom",12));
        System.out.println("userSet" + userSet);
    }
}

class User{

    private int age;

    private String name;

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

    //判断地址是否一样
    //非空判断和class类型判断
    //强转
    //对象里面的字段一一匹配
    @Override
    public boolean equals(Object obj) {

        if(this == obj) return true;

        if(obj == null || getClass() != obj.getClass()) return false;

        User user = (User) obj;

        return age == user.age && name.equals(user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age,name);
    }

}

# 控制台,数据去重
userSet[User{age=12, name='tom'}, User{age=22, name='tony'}, User{age=22, name='jack'}]

# 案例3,idea生成equals和hashCode方法
public class NativeMethodTest {
    public static void main(String [] args){
        Set userSet = new HashSet<>();
        userSet.add(new User("jack",22));
        userSet.add(new User("tom",12));
        userSet.add(new User("tony",22));
        userSet.add(new User("tom",12));
        System.out.println("userSet" + userSet);
    }
}

class User{

    private int age;

    private String name;

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }

}

# 控制台,数据去重
userSet[User{age=12, name='tom'}, User{age=22, name='tony'}, User{age=22, name='jack'}]
  • 使用lombok插件,使用注解@EqualsAndHashCode为实体类生成equals和hascode方法