Set系列集合:添加的元素是无序(添加的数据的顺序和获取出数据顺序不一样),不重复,无索引
如:HashSet:无序,不可重复,无索引
LinkedHashSet:有序,不重复,无索引
TreeSet:按照大小默认升序排序,不重复,无索引
public class java {
public static void main(String[] args) {
//1:创建一个set对象
Set<Integer>set=new HashSet<>();//Set是一个抽象类
set.add(111);
set.add(111);
set.add(444);
set.add(444);
set.add(444);
set.add(888);
set.add(888);
System.out.println(set);//[888, 444, 111]-->HashSet无序,不重复,无索引
}
}
哈希值:
就是一个int类型的数值,java对象都有一个
哈希值
java中所有的对象都可以调用Object类提供的hashCode方法,返回自己对象的哈希值
对象哈希值的特点:
同一个对象多次调用hashCode()方法返回的哈希值是相同的
不同的对象哈希值一般不同,但也有可能相同(哈希碰撞)
HashSet集合的底层原理:
基于哈希表:数组+链表+红黑树
注意:HashSet集合默认不能对内容一样的两个对象去重复!
比如两个相同内容的对象存入到HashSet集合中去,HashSet不能去重复
Student类:
public class Student {
private String name;
private int age;
public Student() {
}
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 +
'}';
}
}
public class test {
public static void main(String[] args) {
HashSet<Student>hashset=new HashSet<>();
hashset.add(new Student("hh",12));
hashset.add(new Student("hh",12));
hashset.add(new Student("aa",88));
System.out.println(hashset);
// [Student{name='aa', age=88}, Student{name='hh', age=12}, Student{name='hh', age=12}]
}
}
方法:重写equals,hashcode方法
@Override//两个对象的内容一样返回true,不重写的话比较的是地址
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() {
return Objects.hash(name, age);
结果:[Student{name='aa', age=88}, Student{name='hh', age=12}]
LinkHashSet:
有序,不重复,无索引
TreeSet:
不重复,无索引,可排序(默认是升序排序,按照元素从大到小默认排序)
对于数值类型:直接按照大小进行排序
对于字符串类型:默认按照首字符的编号升序排序
public class test {
public static void main(String[] args) {
TreeSet<Integer>treeSet=new TreeSet<>();
treeSet.add(12);
treeSet.add(10);
treeSet.add(11);
System.out.println(treeSet);//[10, 11, 12]
}
}
如何实现自定义排序:
直接排序自定义对象会报错
方法一:让自定义的类实现Comparable接口,重写里面的compareTo方法来指定比较规则
//方法一:实现Comparable
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student() {
}
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() {
return Objects.hash(name, age);
}
@Override
public int compareTo(Student o) {
return this.age-o.age;//按照年龄升序
}
}
public class test2 {
public static void main(String[] args) {
TreeSet treeSet =new TreeSet<>();
treeSet.add(new Student("aa",18));
treeSet.add(new Student("cc",20));
treeSet.add(new Student("bb",19));
treeSet.add(new Student("bb",19));
System.out.println(treeSet);//[Student{name='aa', age=18}, Student{name='bb', age=19}, Student{name='cc', age=20}]
}
}
方法二:通过调用TreeSet集合的有参构造器,可以设置comparator对象(用Lambda表达式)
public class test3 {
public static void main(String[] args) {
//方法二:
/*TreeSet<Student>treeSet=new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});*/
TreeSet<Student>treeSet=new TreeSet<>((o1,o2)->o1.getAge()-o2.getAge() );
treeSet.add(new Student("aa",18));
treeSet.add(new Student("cc",20));
treeSet.add(new Student("bb",19));
treeSet.add(new Student("bb",19));
System.out.println(treeSet);
}
}