Java集合框架之Collections工具类
-
Collections 工具类
Collections是一个提供对集合对象进行各种操作的静态方法的工具类,包括排序、搜索、线程安全化、同步控制等- Java里关于集合的工具类,包含有各种有关集合操作的静态方法,不能实例化(把构造函数私有化)
- 和Collection的区别
- Collection是接口,提供了对集合对象进行基本操作的通用接口方法,List、Set等多种具体的实现类
- Collections是工具类,专门操作Collection接口实现类里面的元素
-
常见方法
- 排序 sort(List list)
- 按自然排序的升序排序
- sort(List list, Comparator c) 自定义排序规则,由Comparator控制排序逻辑
- 随机排序 shuffle(List list)
- 排序 sort(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