Java集合框架Collection拓展进阶

Java集合框架之Collections工具类

  • Collections 工具类

    • Collections是一个提供对集合对象进行各种操作的静态方法的工具类,包括排序、搜索、线程安全化、同步控制等
    • Java里关于集合的工具类,包含有各种有关集合操作的静态方法,不能实例化(把构造函数私有化)
    • 和Collection的区别
      • Collection是接口,提供了对集合对象进行基本操作的通用接口方法,List、Set等多种具体的实现类
      • Collections是工具类,专门操作Collection接口实现类里面的元素
  • 常见方法

    • 排序 sort(List list)
      • 按自然排序的升序排序
      • sort(List list, Comparator c) 自定义排序规则,由Comparator控制排序逻辑
      • 随机排序 shuffle(List list)
  • 其他常见方法

    • max(Collection<? extends T> coll): 根据元素的自然顺序返回集合中的最大元素。
    • min(Collection<? extends T> coll): 根据元素的自然顺序返回集合中的最小元素。
    • emptyList(): 返回一个不可变的空列表。
    • singletonList(T o): 返回一个包含指定元素的不可变列表。
    • reverse(List<?> list): 反转列表中元素的顺序。
java 复制代码
package package7;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionsDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("c");
        list.add("b");
        System.out.println(list);
        Collections.sort(list);
        System.out.println("默认升序:" + list);
        // 默认升序
        list.sort(Comparator.naturalOrder());
        System.out.println("升序:" + list);
        // 降序
        list.sort(Comparator.reverseOrder());
        System.out.println("降序:" + list);
        // 随机排序
        Collections.shuffle(list);
        System.out.println("随机:" + list);
        // 最大
        System.out.println("最大:" + Collections.max(list));
        // 最小
        System.out.println("最小:" + Collections.min(list));
    }
}
css 复制代码
[a, c, b]
默认升序:[a, b, c]
升序:[a, b, c]
降序:[c, b, a]
随机:[c, a, b]
最大:c
最小:a

Java集合框架之Comparator排序接口

  • Collections工具类的比较和排序

    • 获取最大元素 max(Collection coll) 默认比较,不适合对象比较
    • 获取最小元素 min(Collection coll) 默认比较,不适合对象比较
    • 进阶:获取最大元素 max(Collection coll, Comparator comparator)
arduino 复制代码
package package7;

import java.util.Objects;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}
java 复制代码
package package7;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionsDemo {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("aaa", 16));
        students.add(new Student("bbb", 17));
        students.add(new Student("ddd", 19));
        students.add(new Student("ccc", 18));
        students.add(new Student("eee", 20));
        System.out.println(students);
        Student maxAgeStudent = Collections.max(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        System.out.println("年龄最大的学生:" + maxAgeStudent);
        Student minAgeStudent = Collections.min(students, (o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println("年龄最小的学生:" + minAgeStudent);
    }
}
arduino 复制代码
[Student{name='aaa', age=16}, Student{name='bbb', age=17}, Student{name='ddd', age=19}, Student{name='ccc', age=18}, Student{name='eee', age=20}]
年龄最大的学生:Student{name='eee', age=20}
年龄最小的学生:Student{name='aaa', age=16}

Java集合框架之Comparable排序接口

  • Comparable 接口

    • 是一个接口,定制排序规则,对实现它的每个类的对象进行整体排序,里面 compareTo 方法是实现排序的具体方法
    • 比如TreeSet、SortedSet、Collections.sort() 方法调用进行排序
    • String、Integer等类默认实现了这个接口,所以可以排序(看源码)
  • compareTo方法

    • 用于比较当前对象和传进来对象的大小,o为要比较的对象
    • 返回int类型
      • 大于0, 表示this大于传进来的对象o ,则往后排,即升序
      • 等于0,表示this等于传进来的对象o
      • 小于0,表示this小于传进来的对象o
  • 总结

    • 如果类的自然排序逻辑就是所需要的排序方式,并且不会改变,那么应该实现Comparable接口。
    • 如果需要为类提供多种排序方式,或者需要对没有实现Comparable接口的类进行排序,那么应该使用Comparator
    • Comparator提供了更高的灵活性,它允许为同一个类定义多个不同的排序方式,并且可以用于比较任何对象
    • Comparable在类的自然排序逻辑简单,且不会改变的情况下更为方便。
arduino 复制代码
package package7;

public class Student1 implements Comparable<Student1>{
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    @Override
    public int compareTo(Student1 o) {
        return this.age - o.age;
    }
}
csharp 复制代码
package package7;

import java.util.Set;
import java.util.TreeSet;

public class ComparableDemo {
    public static void main(String[] args) {
        Set<Student1> set = new TreeSet<>();
        set.add(new Student1("aaa", 16));
        set.add(new Student1("bbb", 17));
        set.add(new Student1("ddd", 19));
        set.add(new Student1("ccc", 18));
        set.add(new Student1("eee", 20));
        System.out.println(set);
    }
}
css 复制代码
[Student{name='aaa', age=16}, Student{name='bbb', age=17}, Student{name='ccc', age=18}, Student{name='ddd', age=19}, Student{name='eee', age=20}]

容器对象比较之重写HashCode和Equals

  • HashCode和Equals方法

    • 用于集合容器里面的对象比较
    • hashCode()equals()Object 类中的两个重要方法。
    • 当自定义类并需要在集合(如HashSet、HashMap)中使用时,经常需要重写这两个方法
  • equals方法

    • 顶级类Object里面的方法,所有类都是继承Object的,返回值boolean类型
    • equals() 方法用于判断两个对象是否相等。
    • 默认情况下,Object 类中的 equals() 方法判断的是两个对象是否是同一个对象(即内存地址是否相同)。
    • 但在实际开发中,通常需要基于对象的属性值来判断对象是否相等。
    • 根据自定义的匹配规则,用于匹配两个对象是否一样, 一般逻辑是如下
  • hashcode方法

    • hashCode() 方法返回该对象的哈希码值。在哈希表结构中,hashCode() 用于确定对象的桶位置(bucket location)
    • 对象的 equals 方法的比较操作用到的信息没有被修改,对该对象调用 hashCode 方法多次,应该始终一致地返回相同的整数
    • 如果两个对象根据 equals(Object) 方法是相等的,调用这两个对象中任一对象的 hashCode 方法都必须产生相同的整数结果
    • 如果两个对象根据 equals(Object) 方法是不相等的,那调用这两个对象中任一对象的 hashCode 方法不一定产生不同的整数
  • 注意以下几点:

    • 一致性:两个方法必须保持一致性,即相等的对象必须具有相同的哈希码。
    • 性能 :避免在 equals() 方法中执行复杂的计算或调用可能改变对象状态的方法。
    • 通用性:如果类继承自其他类,并且父类已经重写了这两个方法,则需要考虑是否需要调用父类的实现
  • 问题:当向集合中插入对象时,如何判别在集合中是否已经存在该对象,比如Set确保存储对象的唯一,并判断是不是同个对象呢?

    • 依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法
    • 判断两个对象是否一样,首先判断插入obj的hashcode值是否存在
    • hashcode值不存在则直接插入集合,值存在,则还需判断equals方法判断对象是否相等
arduino 复制代码
package package7;

import java.util.Objects;

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        int result = Objects.hashCode(name);
        result = 31 * result + age;
        return result;
    }
}
csharp 复制代码
package package7;

public class HashCodeDemo {
    public static void main(String[] args) {
        Student student1 = new Student("Steven Wong", 29);
        Student student2 = new Student("Steven Wong", 29);
        System.out.println(student1.equals(student2));
        System.out.println(student1.hashCode());
        System.out.println(student2.hashCode());
    }
}
diff 复制代码
true
-1592016313
-1592016313
相关推荐
码匠许师傅1 小时前
【C++ 面试真题】聊聊 C++ 的虚函数和多态
java·c++·面试
chuan.bai2 小时前
Java RAG 实战(第 8 篇):Spring Boot RAG 查询 API
java·spring boot·贪心算法
FlyWIHTSKY2 小时前
idea中集成claude功能
java·ide·人工智能·intellij-idea·cloudera
Java成神之路-2 小时前
Spring AI 统一结构化返回:ChatModel / ChatClient 两种实现方式
java·springaialibaba
Mr. zhihao2 小时前
深度解析:为什么Java序列化需要搭配ByteArrayOutputStream?IO装饰器模式的精妙设计
java·开发语言·装饰器模式
存在morning2 小时前
【Python 开发实践 一】Python vs Go vs Java 三门语言对比
java·python·golang
vx-程序开发2 小时前
springboot旅游推介平台---附源码24175
java·spring boot·python·spring cloud·eclipse·django·idea
艾莉丝努力练剑2 小时前
【QT:解决问题】Qt5Core.dll:无法定位程序输入点
java·开发语言·qt·学习·面试
小蒜学长2 小时前
“喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·宠物