Collection-Set 迷南。 2023-10-07 18:32 12阅读 0赞 > Set系列集合:添加的元素是无序的,不重复,无索引 > \* --HashSet:无序的,不重复,无索引 > \* --LinkedHashSet:有序,不重复,无索引 > \* --TreeSet:按照大小默认升序,不重复,无索引 > > \*foreach,Lambda,迭代器 > HashSet:无序的,不重复,无索引 > \* 面试题: > \* >Set集合添加的元素是不重复的,是如何去重复的 > \* 对于有值特性的,Set集合可以直接判断进行去重 > \* 对于引用数据类型的类对象,Set集合是按照: > \* Set集合会让两两比较,先调用自己的hashCode()方法得到彼此的哈希值(所谓的\* 内存地址) > \* 然后比较两个对象的哈希值是否相同,如果不相同直接认为两个对象不重复 > \* 如果哈希值相同,会继续让两个对象进行equals比较内容是否相同,如果相同认\*\* 为真的就重复了 > \* 如果不同认为不重复 > \* 集合会让对象调用hashCode()方法获取两个对下那个的哈希值比较 > \* / \\ > \* false true > \* / \\ > \* 不重复 继续让两个对象进行equals比较 > \* / \\ > \* false true > \* / \\ > \* 不重复 重复 > \* >Set集合元素无序的原因是是什么 > \* Set系列集合添加元素无序的根本原因就是因为底层采用了哈希表的存储元素 > \* jdk1.8之前:哈希表= 数组 + 链表 + (哈希算法) > \* jdk1.8之后:哈希表 = 数组 + 链表 + 红黑树 + (哈希算法) > \* 哈希算法(散列) > \* 1,先获取元素对对象的哈希值, > \* 2,让当前对象的哈希值对应的底层数组长度求余 > \* 3,求余的结果作为该对象元素在底层数组的索引位置 > \* 4,把该对象元素存到该索引位置 > \* > \* 小结: > \* Set系列集合就是基于哈希表存储数据的 > \* 它的增啥改查性能都很好,但是它是无序不重复的 public class DemoHashSet { public static void main(String[] args) { //无序,不重复,无索引 HashSet<String> set = new HashSet<>(); set.add("Mybatis"); set.add("Java"); set.add("MySQL"); set.add("Spring"); System.out.println(set);//[Java, MySQL, Spring, Mybatis] //储存一些自定义类型数据:无序不重复 Set<Apple> Apple = new HashSet<>(); Apple a1 = new Apple("阿克苏", 2); Apple a2 = new Apple("红富士", 2); Apple a3 = new Apple("阿克苏", 2); Apple.add(a1); Apple.add(a2); Apple.add(a3); System.out.println(Apple); //[Apple{name='红富士', price=2}, Apple{name='阿克苏',price=2}] } } class Apple{ private String name; private int price; public Apple(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { return "Apple{" + "name='" + name + '\'' + ", price=" + price + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Apple apple = (Apple) o; return price == apple.price && Objects.equals(name, apple.name); } @Override public int hashCode() { return Objects.hash(name, price); } } > LinkedHashSet是hashSet的子类,元素是有序,不重复,无索引 > \* LinkedHashSet底层依然是使用哈希表存储元素 > \* 但是每个元素都额外带一个链维护添加顺序 > \* 不光是增啥改查快,还有序,缺点就是多一个存储顺序的链会栈内存空间,而且不允许重复 > \* 总结: > \* 如果希望元素可以重复,又有索引,查询快用ArrayList集合 > \* 如果元素希望可以重复,又有索引,增啥改查快LinkedList集合 > \* 如果希望增啥改查都快,氮元素不重复以及无序无索引,HashSet > \* 如果希望增删改查快有序,但是元素不重复以及无索引,那么就用LinkedHashSet集合 public class DemoLinkedHashSet { public static void main(String[] args) { Set<String> strings = new LinkedHashSet<>(); strings.add("王五"); strings.add("张三"); strings.add("李四"); strings.add("张三"); System.out.println(strings);//[王五, 张三, 李四] } } > TreeSet:不重复,无索引,按照大小默认升序排序 > \* TreeSet集合称为排序不重复集合,可以对元素进行默认的升序排序 > \* > \*TreeSet集合自排序的方式 > \* 1,有值特性的元素直接可以升序排序,可以对元素进行默认的升序排序 > \* 2,字符串类型的元素会按照首字符的编号排序 > \* 3,对于自定义的引用数据类型,TreeSet默认无法排序 > \*自定义的引用数据类型的排序实现 > \* 对于自定义的引用类型数据类型,TreeSet默认无法排序 > \* 所以需要定制排序的大小规则: > \* a,直接对对象的类实现比较器规则接口Comparable,重写比较方法 > \* 比较者大于被比较者,返回正数 > \* \* 比较者小于被比较者,返回负数 > \* \* 比较者等于被比较者,返回0 > \* b,直接为集合设置比较器Comparator对象,重写比较方法 > \* 比较者大于被比较者,返回正数 > \* 比较者小于被比较者,返回负数 > \* 比较者等于被比较者,返回0 > \* 注意:如果类和集合都带有比较规则,优先使用集合自带的比较规则 > \* 小结: > \* TreeSet对于自定义的引用类型数据类型,TreeSet默认无法排序 > \* 需要定制排序的大小规则: > \* a,直接对对象的类实现比较器规则接口Comparable,重写比较方法 > \* b,直接为集合设置比较器Comparator对象,重写比较方法 > \* 如果类和集合都带有比较规则,优先使用集合自带的比较规则 public class DemoTreeSet{ public static void main(String[] args) { //TreeSet无序不重合 Set<Double> scores = new TreeSet<>(); scores.add(100.0); scores.add(99.0); scores.add(0.01); scores.add(34.5); scores.add(54.3); System.out.println(scores);//[0.01, 34.5, 54.3, 99.0, 100.0] //字符串按照首字符的编号进行排序 TreeSet<String> names = new TreeSet<>(); names.add("ABCD"); names.add("李四"); names.add("abcd"); names.add("张三"); System.out.println(names);//[ABCD, abcd, 张三, 李四] //引用类型定义TreeSet集合 Set<Employee> employees = new TreeSet<>(); employees.add(new Employee("张三", 250, 150)); employees.add(new Employee("李四", 50, 140)); employees.add(new Employee("王五", 150, 180)); employees.add(new Employee("赵六", 520, 10)); System.out.println(employees); //cannot be cast to class java.lang.Comparable (没有implements Comparable<Employee>) //implements Comparable<Employee> //[Orange{name='赵六', sales=520.0, weight=10}, Orange{name='李四', sales=50.0, weight=140}, Orange{name='张三', sales=250.0, weight=150}, Orange{name='王五', sales=150.0, weight=180}] //集合自带比较器对象 //如果类和集合都存在大小规则,默认使用集合自带的规则进行大小排序 Set<Employee> employees1 = new TreeSet<>(new Comparator<Employee>() { @Override public int compare(Employee o1, Employee o2) { //o1比较者,o2被比较者 return o1.getWeight() - o2.getWeight(); } }); employees1.add(new Employee("张三", 250, 150)); employees1.add(new Employee("李四", 50, 140)); employees1.add(new Employee("王五", 150, 180)); employees1.add(new Employee("赵六", 520, 10)); System.out.println(employees1); //[Orange{name='赵六', sales=520.0, weight=10}, Orange{name='李四', sales=50.0, weight=140}, Orange{name='张三', sales=250.0, weight=150}, Orange{name='王五', sales=150.0, weight=180}] } } class Employee implements Comparable<Employee>{ private String name; private double sales; private int weight; public Employee(String name, double sales, int weight) { this.name = name; this.sales = sales; this.weight = weight; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSales() { return sales; } public void setSales(double sales) { this.sales = sales; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } @Override public String toString() { return "Orange{" + "name='" + name + '\'' + ", sales=" + sales + ", weight=" + weight + '}'; } //重写比较方法 比较者:this,被比较者:o @Override public int compareTo(Employee o) { return this.weight - o.weight; }
还没有评论,来说两句吧...