展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

集合框架拓展

  • 迭代器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<String> set = new HashSet<>();
   set.add("jack");
   set.add("tom");
   set.add("marry");
   set.add("tony");
   set.add("jack");

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

# 迭代list集合
 public static void testList(){
   List<String> 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<String> iterator = list.iterator();
   while (iterator.hasNext()){
       String str = iterator.next();
       System.out.println(str);
   }
}

# 迭代map集合
    public static  void testMap(){
        Map<String,String> map = new HashMap<>();
        map.put("jack","广东");
        map.put("tim","广西");
        map.put("marry","海南");
       Set<Map.Entry<String,String>> entrySet = map.entrySet();
       Iterator<Map.Entry<String,String>> iterator = entrySet.iterator();
       while (iterator.hasNext()){
           Map.Entry<String,String> entry = iterator.next();
             String str =  entry.getKey() +" = " + entry.getValue();
             System.out.println(str);
       }
    }
  • 迭代器注意事项
# 如下在迭代过程中直接使用list集合的remove方法删除元素,报错
public static void testList(){
 List<String> 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<String> 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<String> 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<String> 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<String> 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<String> iterator = list.iterator();
 while (iterator.hasNext()){
     String str = iterator.next();
     if("jack".equals(str)){
         iterator.remove(str);
     }
     System.out.println(str);
     }
 }
  • 升序排序
List<String> list = new ArrayList<>();
list.add("aaaa");
list.add("zzz");
list.add("gggg");
Collections.sort(list);
System.out.println(list);
  • 降序排序
List<String> 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<String> 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<Student> 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<Student>() {
           @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<Student>() {
           @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<Student> {

    @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<String> list = new ArrayList<>();
list.add("SpringBoot课程");
list.add("架构课程");
list.add("微服务SpringCloud课程"); 
list = Collections.unmodifiableList(list);    //设置为只读List集合
System.out.println(list);

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

Map<String, String> 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<Student> 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<Student> 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<User> 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<User> 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<User> 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方法
posted @ 2022-05-02 21:20  DogLeftover  阅读(21)  评论(0编辑  收藏  举报