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;}@Overridepublic 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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic 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>() {@Overridepublic 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);}
}