Set及其三个子类

it2022-05-05  115

Set及其三个子类

HashSet

(1)概述:

​ 元素无序(存取顺序不一致)且唯一

​ HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null ​ 哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)

(2)原理:

​ 当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。

(3)HashSet 集合判断两个元素相等的标准:

​ 两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

​ 结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

​ 合理重写hashCode 方法,是为了减少调用equals()的次数,也称之为减少碰撞

@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); }

(4)展示:

public class Demo1 { public static void main(String[] args) { HashSet<Integer> objects = new HashSet<>(); objects.add(1); objects.add(12); objects.add(11); objects.add(11); objects.add(11); objects.add(13); objects.add(14); for (Integer object : objects) { System.out.println(object); } System.out.println("------------------------"); HashSet<String> str = new HashSet<>(); str.add("qwetrt"); str.add("qw"); str.add("啊啊啊"); str.add("啊啊啊"); str.add("我我我我"); str.add("qweetyuurrrr"); for (String s : str) { System.out.println(s); } } }

结果:

1 11 12 13

14


我我我我 qweetyuurrrr qw qwetrt 啊啊啊

LinkedHashSet

(1)概述:

​ LinkedHashSet 底层数据结构是链表和哈希表 元素有序且唯一 链表保证了有序,哈希表保证了唯一。 线程不安全效率高。

(2)举例:

public class Demo { public static void main(String[] args) { LinkedHashSet<String> strings = new LinkedHashSet<>(); strings.add("bbb"); strings.add("aaa"); strings.add("ccc"); strings.add("ddd"); strings.add("aaa"); strings.add("bbb"); strings.add("ccc"); strings.add("ddd"); for (String string : strings) { System.out.println(string); } } }

结果:

bbb aaa ccc ddd

TreeSet

(1)概述:

​ TreeSet 元素唯一,且可以对元素进行排序, 底层数据结构是二叉树

(2)举例:

public class Demo1 { public static void main(String[] args) { TreeSet<Integer> treeSet = new TreeSet<>(); treeSet.add(20); treeSet.add(18); treeSet.add(23); treeSet.add(22); treeSet.add(17); treeSet.add(24); treeSet.add(19); treeSet.add(18); treeSet.add(24); System.out.println(treeSet); } }

结果:

[17, 18, 19, 20, 22, 23, 24]

(3)自然排序:

​ 如果采用的是空参构造,那么采用的就是自然排序

​ 如果是自然排序,那么对元素有要求,要求元素必须实现一个Comparable接口,重写这个接口中的一个compareTo这个比较的方法,根据此方法的返回值的正 负 0 来决定元素,排列的位置

public class Demo1 { public static void main(String[] args) { TreeSet<Student> treeSet = new TreeSet<>(); treeSet.add(new Student("张三士大夫士大夫", 23)); treeSet.add(new Student("张三是非得失", 23)); treeSet.add(new Student("李四大幅度发", 23)); treeSet.add(new Student("王五大幅度发", 20)); treeSet.add(new Student("周六的", 30)); treeSet.add(new Student("田七大幅度", 23)); treeSet.add(new Student("李白大幅度发", 33)); treeSet.add(new Student("刘星大幅度发", 63)); treeSet.add(new Student("夏雨", 78)); treeSet.add(new Student("张子豪", 53)); for (Student student : treeSet) { System.out.println(student); } } static 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 int compareTo(Student student) { //根据学生的年龄大小来排序 //年龄一样,并不能说明是同一个对象,我们还得比较姓名是否一样 int num=this.age-student.age; int num2=num==0?this.name.compareTo(student.name):num; return num2; //根据返回值的正 负 0 来决定元素的放置位置 } } }

结果:

Student{name=‘王五大幅度发’, age=20} Student{name=‘张三士大夫士大夫’, age=23} Student{name=‘张三是非得失’, age=23} Student{name=‘李四大幅度发’, age=23} Student{name=‘田七大幅度’, age=23} Student{name=‘周六的’, age=30} Student{name=‘李白大幅度发’, age=33} Student{name=‘张子豪’, age=53} Student{name=‘刘星大幅度发’, age=63} Student{name=‘夏雨’, age=78}

(4)比较器排序

​ 就是我们在创建TreeSet对象时,给他传入一个比较器,重写比较器里面的compare方法,根据此方法的返回值的正负 0来决定元素的放置顺序

public class Demo { public static void main(String[] args) { MyComparator myComparator = new MyComparator(); TreeSet<Student> treeSet = new TreeSet<>(myComparator); treeSet.add(new Student("张三士大夫士大夫", 23)); treeSet.add(new Student("张三是非得失", 23)); treeSet.add(new Student("李四大幅度发", 23)); treeSet.add(new Student("王五大幅度发", 20)); treeSet.add(new Student("周六的", 30)); treeSet.add(new Student("田七大幅度", 23)); treeSet.add(new Student("李白大幅度发", 33)); treeSet.add(new Student("刘星大幅度发", 63)); treeSet.add(new Student("夏雨", 78)); treeSet.add(new Student("张子豪", 53)); for (Student student : treeSet) { System.out.println(student); } } static class MyComparator implements Comparator<Student> { @Override public int compare(Student s1, Student s2) { //按照年龄大小排序 int num = s1.getAge() - s2.getAge(); int num2=num==0?s1.getName().compareTo(s2.getName()):num; return num2; } } static 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 + '}'; } } }

结果:

Student{name=‘王五大幅度发’, age=20} Student{name=‘张三士大夫士大夫’, age=23} Student{name=‘张三是非得失’, age=23} Student{name=‘李四大幅度发’, age=23} Student{name=‘田七大幅度’, age=23} Student{name=‘周六的’, age=30} Student{name=‘李白大幅度发’, age=33} Student{name=‘张子豪’, age=53} Student{name=‘刘星大幅度发’, age=63} Student{name=‘夏雨’, age=78}


最新回复(0)