Java单列集合

集合

1.集合的来由

  • 数组的不足:

    • 无法扩展:数组本身的长度是固定的,一旦创建,就无法修改

    • 结果:每次要添加一个新元素的时候,就需要创建一个新的数组,长度为原来的数组长度+1,将原来数组中的所有元素都拷贝到新数组中,添加新元素这些操作和真正的业务逻辑无关

  • 解决:

    • 为了解决这一限制,Java 提供了一系列的类,它们被称为集合框架。

  • 集合和数组的异同:

  • 共同点:

    • 都是用于存储数据的容器

    • 使用容器的原因,就是希望使用有规律的索引、操作方式,操作那些没有规律的元素

  • 不同点:

    • 存储内容的不同

      • 数组既可以存储基本类型,也可以存储引用类型

      • 集合只能存储引用类型,如果需要存储基本数据类型 ,其实里面存的是包装类对象

  • 存储数量的不同:

    • 数组的长度不可变,一旦确定大小就无法改变

    • 集合的长度可变,是一个可以伸缩的容器

  • 方法不同:

    • 数组中只有Object中定义的方法,以及有一个length属性

    • 集合中可以有很多方法,很丰富

  • 集合的体系结构

    • 集合分类:

      • 单列集合:每个元素都是一个单独的个体

      • 双列集合:每个操作都是针对一对数据来进行的,一对数据作为一个单位,类似字典

image-20230208110411083

  • 集合的体系介绍

    • List

      为了实现容器容量可变,提供 List 接口,其中定义了新增元素、删除元素等动态操作容器的方法。List 接口继承自 Collection 接口。

      List 下的主要实现类有:ArrayList、LinkedList

    • Set

      为了实现容器中元素不可重复,提供 Set 接口,其中同样提供基础的操作容器的方法。Set 接口继承自Collection 接口。

      Set 下的主要实现类有:HashSet、TreeSet

    • Map

      为了实现关联性数据的存储,提供 Map 接口,也叫双列集合、K-V 集合、键值对集合,其中 Key 不可重复,Map 是 Set 的实现原理,Set 就是单独使用 Map 的 Key 来实现的。

      Map 下的主要实现类有:HashMap、TreeMap

2.Collection

2.1 Collection概述和常用方法

  • 单词:收集、集合

  • 单列集合的顶层接口,定义的是所有单列集合中共有的功能。

  • image-20230208225259044

  • 常用方法:

    • add(Object obj):将obj元素添加到集合中

    • remove(Object obj):将obj元素从集合中删除

    • clear():将集合中的元素清空

    • isEmpty():判断集合中元素是否为空

    • contains(Object obj):判断集合中是否包含obj元素

    • size():返回集合中的元素个数

  • 示例代码

  • import java.util.Collection;
    import java.util.ArrayList;
    
    /**
     * Collection概述和常用方法
     */
    public class Simple01 {
        public static void main(String[] args) {
            Collection c1 = new ArrayList();
            c1.add("a");
            c1.add("b");
            c1.add("c");
            c1.add("d");
            c1.add("xyz");
            c1.add(123);
            System.out.println(c1);//说明重写了集合的toString方法
            c1.remove("a");
            c1.remove("b");
            c1.remove("xyz");
            c1.remove(123);
            System.out.println(c1);
            System.out.println(c1.contains("c"));//true
            System.out.println(c1.contains(123));//false
            System.out.println(c1.isEmpty());
    
            System.out.println(c1.size());
            c1.clear();
            System.out.println(c1);
            System.out.println(c1.isEmpty());
        }
    }

2.2 Collection的第一种遍历方式

  • 转成数组,通过遍历数组的方式,来间接的遍历集合,Object[] toArray():将调用者集合转成Object类型的数组

  • 示例代码:

  • /**
     * Collection的第一种遍历方式  toArray();
     */
    public class Simple02 {
        public static void main(String[] args) {
            // test1();
            test2();
        }
    
        public static void test1() {
            Collection c1 = new ArrayList();
            c1.add(111);
            c1.add(222);
            c1.add(333);
            c1.add(444);
            c1.add("aaa");
            c1.add("bbb");
            System.out.println(c1);
            // Object[] toArray():
            Object[] objects = c1.toArray();
            for (Object object : objects) {
                System.out.println(object);
            }
    
        }
    
        public static void test2() {
            Collection c2 = new ArrayList();
    
            c2.add(new Person("zs"));
            c2.add(new Person("ls"));
            c2.add(new Person("ww"));
            // [Person{name='zs'}, Person{name='ls'}, Person{name='ww'}]
            System.out.println(c2);
            Object[] objects = c2.toArray();
            for (Object object : objects) {
                // System.out.println(object);
                // 如何只输出name的值?
                // System.out.println(object.getName());
                // 向下转型
                if (object instanceof Person) {
                    Person object1 = (Person) object;
                    System.out.println(object1.getName());
                }
            }
        }
    
    }
    
    class Person {
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

2.3 集合遍历的第二种方式:迭代器

  • 迭代:更迭、更新换代,有从某一个到下一个的过程的含义

  • 迭代器:专门用于将集合中的元素,一个到另一个逐个进行迭代的对象

  • 获取:集合自己内部就有一个可以迭代自己的对象,从集合对象中获取即可

  • 语法:

    • 类型 Iterator it = collection.iterator()

  • 迭代器的使用:

    • 方法iterator() 返回的是一个Iterator接口的实现类对象,可以使用的就是Iterator接口中的方法:

    • hasNext():判断集合中是否还有下一个元素

    • next():获取集合中的下一个元素

    • remove():删除迭代器对象正在迭代的那个对象

    • 示例代码

  • 执行方式

  • image-20230208113723688

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 集合遍历的第二种方式:迭代器
 */
public class Simple04 {
    public static void main(String[] args) {
        // test1();
        // test2();
        // test3();
        test4()
    }

    public static void test1() {
        Collection c1 = new ArrayList();
        c1.add(123);
        c1.add(456);
        c1.add(789);
        Iterator iterator = c1.iterator();
        System.out.println(iterator.hasNext());
        System.out.println(iterator.next());
        System.out.println(iterator.hasNext());
        System.out.println(iterator.next());
        System.out.println(iterator.hasNext());
        System.out.println(iterator.next());
        System.out.println(iterator.hasNext());
        System.out.println(iterator.next());
    }

    public static void test2() {
        Collection c2 = new ArrayList();
        c2.add(123);
        c2.add(456);
        c2.add(789);
        Iterator iterator = c2.iterator();
        while (iterator.hasNext()) {
            Integer integer = (Integer) iterator.next();
            System.out.println(integer);
        }
    }

    public static void test3() {
        Collection c3 = new ArrayList();
        c3.add(new Person("zs"));
        c3.add(new Person("ls"));
        c3.add(new Person("ww"));
        Iterator iterator = c3.iterator();
        while (iterator.hasNext()) {
            Person p = (Person) iterator.next();
            System.out.println(p.getName());
        }
    }
  
   static void test4 () {
         Collection c =new ArrayList();
         for (int i = 0; i < 50; i++) {
             c.add(i);
         }
//         for (Object o : c) {
//             if (o.equals(10) ) {
                 c.remove(o); // 触发异常
//             }
//             System.out.println(o);
//         }
         Iterator<Integer> iterator = c.iterator();
         while (iterator.hasNext()) {
             int i =  iterator.next();
             if (i == 10) {
                 iterator.remove();
                 System.out.println("ok");
             }
             System.out.println(i);
         }
         System.out.println(c);
}
}

3.List

3.1概述

  • 是Collection的一个子接口

  • 特点:

    • 有序:每个元素都有自己的位置(存储的顺序与取出的顺序是一致的)

    • 有索引

    • 可以重复

  • 特有方法:

    • add(int index, Object obj):在指定索引上,添加指定的元素

    • remove(int index):删除指定索引上的值

    • set(int index, Object obj):将指定索引上的值,修改为指定的值

    • get(int index):根据给定的索引,获取对应位置的值

  • 代码示例

  • import java.util.ArrayList;
    import java.util.List;
    
    public class Simple05 {
        public static void main(String[] args) {
            List list = new ArrayList();
            list.add(0, "abc");
            list.add(1, "def");
            list.add(2, "ghi");
            System.out.println(list);
            list.remove(0);
            System.out.println(list);
            list.set(0, "abc");
            System.out.println(list);
            System.out.println(list.get(1));
        }
    }

3.2 第三种遍历方式

  • 可以通过集合的size方法获取list集合索引的范围,根据索引通过get方法可以获取指定索引的值。

  • 代码示例

  • import java.util.ArrayList;
    import java.util.List;
    
    public class Simple06 {
        public static void main(String[] args) {
            List list = new ArrayList();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            list.add("e");
            for (int i = 0; i < list.size(); i++) {
                //  System.out.println(list.get(i));
                String s = (String) list.get(i);
                System.out.println(s);
            }
        }
    }

3.3 List的实现类

  • 概述

    • List只是一个接口,根据底层实现方式的不同,具有不同的实现类

    • ArrayList:数组实现,顺序存储

    • LinkedList:节点实现,链式存储

    • Vector:数组实现,顺序存储

      • 在jdk1.0版本出现,现在这个类已经过时,在jdk1.2之后,被ArrayList取代

      • 特点:

        • 线程安全,效率较低

        • 顺序存储,增删较慢

    • 特有方法:

      • addElement(Object obj):添加元素

      • removeElement(Object obj):删除元素

      • elements():获取Vector集合的枚举对象,用于遍历集合

    • 特有遍历方式:

      • 使用elements方法获取Enumeration对象

      • 使用Enumeration对象的hasMoreElements方法判断是否有下一个元素

      • 如果有下一个元素,就使用nextElement方法来获取下一个元素

    • 示例代码

    • import java.util.Vector;
      import java.util.Enumeration;
      /**
       * Vector
       */
      public class VectorDemo  {
          public static void main(String[] args) {
              Vector v1 = new Vector();
              v1.addElement(123);
              v1.addElement(456);
              v1.addElement("abc");
              v1.addElement("xyz");
      
              //elements获取用于迭代的枚举对象
              Enumeration en = v1.elements();
              //使用循环,判断是否有下一个元素
              while (en.hasMoreElements()) {
                  System.out.println(en.nextElement());
              }
          }
      }

3.4 ArrayList

ArrayList 的底层实现方式为数组

image-20230208164053649

  • 也是List的一个实现类

  • 没有什么特有方法,只是List的实现类

  • ArrayList 的底层实现方式为数组

  • 存储方式:

    • 数组实现,顺序存储

  • 特点:数据是互相挨着连续的

    • 查询、修改较快, 可以根据索引查询和修改

    • 插入、删除较慢

    • 尾增尾删效率不低的

  • 代码示例:见List-->概述-->代码示例

    • add(int index, Object obj):在指定索引上,添加指定的元素

    • remove(int index):删除指定索引上的值

    • set(int index, Object obj):将指定索引上的值,修改为指定的值

    • get(int index):根据给定的索引,获取对应位置的值

3.5 LinkedList

LinkedList 的底层实现方式为双向链表

image-20230208164303348

  • List的一个实现类

  • LinkedList 的底层实现方式为双向链表

  • 存储方式:

    • 节点实现,链式存储

    • 不通过物理内存位置的相邻,来表示逻辑顺序的相邻

    • 每个元素都存储在一个节点中,节点除了元素数据本身以外,还需要存储下一个元素的内存地址

  • 视图:

  • image-20230208172242422

  • 特点:

    • 查询速度慢:要根据前面的节点来获取后一个节点的地址,前面所有节点都要访问一遍,节点数量越多,查询速度越慢

    • 增删速度快:增删一个元素,只需要修改新增元素前后的两个节点的引用域即可,与集合本身的元素个数无关。

    • LinkedList的特有方法 (使用时请注意多态)

      • 由于在LinkedList中,维护了链表的头和尾节点的对象地址,所以操作头部和尾部非常容易,提供了大量的操作头和尾的方法。

      • addFirst(Object obj):在头部添加元素

      • addLast(Object obj):在尾部添加元素

      • removeFirst():删除头部元素

      • removeLast():删除尾部元素

      • getFirst():获取头部元素

      • getLast():获取尾部元素

    • 代码示例:

    • import java.util.LinkedList;
      
      public class Simple07 {
          public static void main(String[] args) {
              LinkedList lk = new LinkedList();
              lk.addFirst("aaa");
              lk.addFirst("bbb");
              System.out.println(lk);
              lk.addLast("ccc");
              lk.addLast("ddd");
              System.out.println(lk);
              Object o = lk.removeFirst();
              System.out.println(o);
              System.out.println(lk);
              Object o1 = lk.removeLast();
              System.out.println(o1);
              System.out.println(lk);
              System.out.println(lk.getFirst());
              System.out.println(lk.getLast());
          }
      }

4.泛型

4.1泛型的概述和使用【熟练掌握】

  • 泛型:广泛的类型,在定义一个类的时候,类型中有些方法参数、返回值类型不确定,就使用一个符号来表示那些尚未确定的类型,这个符号,就称为泛型。

  • Java 泛型有三种使用方式:泛型类、泛型方法、泛型接口

  • 使用:对于有泛型的类型,在这些类型后面跟上尖括号,尖括号里面写上泛型的确定类型

    (在使用某个类创建对象时,已经可以确定这个具体的类型了,那么就直接写出具体类型)

  • 例如:ArrayList<Integer> al = new ArrayList<>();

  • 泛型的好处:

    • 提高了数据的安全性,将运行时的问题,提前暴露在编译时期

    • 避免了强转的麻烦

  • 注意事项:

    • 前后一致:在创建对象时,赋值符号前面和后面的类型的泛型,必须一致

    • 泛型推断:如果前面的引用所属的类型已经写好了泛型,后面创建对象的类型就可以只写一个尖括号,尖括号中可以不写任何内容。<>特别像菱形,称为“菱形泛型”,jdk1.7特性

    • 代码示例

    • import java.util.ArrayList;
      import java.util.List;
      
      /**
       * 泛型的概述和使用
       */
      public class Simple08 {
          public static void main(String[] args) {
              //  test1(); // 不使用泛型
      				//  test2(); // 使用泛型
              Animal<Integer> animal = new Animal();
              animal.setName("zs");
              animal.setAge(20);
          }
      
          public static void test2() {
              // 使用泛型
              List<Integer> list = new ArrayList();
              list.add(111);
              list.add(222);
      //      list.add("aaa");
      
              for (int i = 0; i < list.size(); i++) {
                  Integer integer = (Integer) list.get(i);
                  System.out.println(integer);
              }
      
          }
      
          public static void test1() {
              // 不使用泛型
              List list = new ArrayList();
              list.add(111);
              list.add(222);
              list.add("aaa");
      
              for (int i = 0; i < list.size(); i++) {
                  Integer integer = (Integer) list.get(i);
                  System.out.println(integer);
              }
      
          }
      }
      
      class Animal<T> {
          private String name;
          private T age;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public T getAge() {
              return age;
          }
      
          public void setAge(T age) {
              this.age = age;
          }
      }
      
      public class Simple {
          public static void main(String[] args) {
              Simple simple = new Simple();
              simple.test1(12,"zs");
          }
      
          public  <T extends  CharSequence,K> T test1 (K k,T t) {
              System.out.println(k);
              System.out.println(t);
              return  t;
          }
      }

5.Set

5.1 Set的概述

  • Set是Collection的另一个子接口

  • 特点:

    • 无序:没有任何前后的分别,所有的元素没有位置的概念,所有的元素都在集合中

    • 没有索引:集合中没有任何位置,元素也就没有位置的属性

    • 不能重复:没有位置的区分,相同值的元素没有任何分别,所以不能重复,数据唯一

  • Set的实现类:

    • HashSet:使用哈希表(查询的速度非常快)的存储方式存储元素的Set集合

    • 哈希表存储原理(数组+链表/红黑树)

  • 存储特点:

    • 相同的元素无法存储进Set集合

    • 集合本身不保证顺序:存储的顺序和取出的顺序不保证一致

  • 示例代码

  • /**
     * Set的概述
     */
    public class Simple09 {
        public static void main(String[] args) {
            Set<String> set = new HashSet();
            set.add("aaa");
            set.add("bbb");
            set.add("cccc");
            set.add("ddd");
            set.add("aaa");
            System.out.println(set);
            // Set 无法使用get(索引) 需要转成List并从List获取指定索引
            ArrayList<String> strings = new ArrayList<>(set);
            System.out.println(strings.get(2));
    
    
        }
    }

5.2 Set集合的遍历

  • 没有自己特有的方法,只能使用Collection接口中定义的方法,只能使用Collection的遍历方式

  • 第一种:转成数组,toArray(),不带泛型的转数组,得到的是Object类型的数组。

  • 第二种:迭代器

  • 第三种:增强for循环

    • 本质:

      • 底层还是迭代器,只不过使用这种格式更加简洁

      • 注意事项:

        • 使用增强for,没有拿到元素的索引,无法修改集合或者数组中的元素值

  • 示例代码1:

  • import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * Set集合的遍历转数组  代码示例1
     */
    import java.util.HashSet;
    import java.util.Set;
    
    public class Simple10 {
        public static void main(String[] args) {
            Set<String> set = new HashSet();
            set.add("aaa");
            set.add("bbb");
            set.add("ccc");
            set.add("ddd");
            Object[] objects = set.toArray();
            for (int i = 0; i < objects.length; i++) {
                System.out.println(objects[i]);
            }
        }
    }

  • 代码示例2:

  • import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    /**
     * Set集合的遍历  代码示例2
     */
    
    public class Simple11 {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("abc");
            set.add("aa");
            set.add("bb");
            set.add("cc");
            set.add("qq");
            set.add("xyz");
    
            Iterator<String> it = set.iterator();
            while(it.hasNext()) {
                String str = it.next();
                System.out.print(str + " ");
            }
        }
    }

  • 代码示例3:

  • import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    /**
     * Set集合的遍历  代码示例3
     */
    
    public class Simple12 {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("abc");
            set.add("aa");
            set.add("bb");
            set.add("cc");
            set.add("qq");
            set.add("xyz");
    
            for (String str : set) {
                System.out.print(str + " ");
            }
            System.out.println();
    
        }
    
    }

  • HashSet 的底层实现方式为哈希表

    image-20230208230326903

  • HashSet是如何使用哈希表存储数据的?

  • Jdk1.8以前哈希表=数组+链表

  • Jdk1.8以后哈希表=(数组+链表/红黑树)

  • HashSet原理

    • 我们使用Set集合都是需要去掉重复元素的,如果在存储的时候逐个equals()比较,效率比较低,哈希算法提高了去重复的效率,降低了使用equals()方法的次数。

    • 当HashSet调用add()方法存储对象的时候,先调用对象的hashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的的对象,如果没有哈希值相同的对象就直接存入集合;如果有哈希值相同的对象,就和哈希值相同的对象逐个进行equals()方法比较,比较结果为false就存入集合,true就不存入集合。

  • import java.util.HashSet;
    
    /**
     * @author Petrel
     */
    public class HashSetDemo {
        public static void main(String[] args) {
           public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            String s1 = new String("abc");
            String s2 = "abc";
            set.add(s1);
            set.add(s2);
            System.out.println(s1.hashCode());
            System.out.println(s2.hashCode()); // 96354
            System.out.println(set);
            set.add("重地");
            set.add("通话");
            System.out.println("重地".hashCode());
            System.out.println("通话".hashCode()); //1179395
            System.out.println(set);
        }
        }
    }

5.3 HashSet存储自定义类型的元素

  • 实验过程: HashSet存储自定义类型的元素,发现《没有保证》元素的唯一性

  • 代码示例:

  • /**
     * HashSet存储自定义类型的元素
     */
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Simple13 {
        public static void main(String[] args) {
            HashSet<Person1> set = new HashSet<>();
            Person1 p1 = new Person1("zhangsan", 13); 0
            Person1 p2 = new Person1("zhangsan", 13); 0 
            Person1 p3 = new Person1("zhangsan", 18); 0 
            Person1 p4 = new Person1("lisi", 18);
            set.add(p1);
            set.add(p2);
            set.add(p3);
            set.add(p4);
            for (Person1 person1 : set) {
                System.out.println(person1);
            }
        }
    }
    
    class Person1 {
        private String name;
        private int age;
    
        public Person1(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;
        }
    }

  • 保证元素唯一性的操作原理

    • 重写hashCode (hashCode返回对象的哈希码值,确定对象的地址)

      • 相同的对象,一定要有相同的哈希值

      • 不同的对象,尽量有不同的哈希值

      • 结论:相同hash值 无法确定是相同对象

  • 重写equals方法:

    • 比较的就是各个对象的属性值,是否全都相同

  • 代码示例:

  • import java.util.HashSet;
    import java.util.Objects;
    
    /**
     * @author Petrel
     */
    public class Simple13 {
        public static void main(String[] args) {
            HashSet<Person1> set = new HashSet<>();
            Person1 p1 = new Person1("zhangsan", 13);
            Person1 p2 = new Person1("zhangsan", 13);
            Person1 p3 = new Person1("zhangsan", 18);
            Person1 p4 = new Person1("lisi", 18);
            set.add(p1);
            set.add(p2);
            set.add(p3);
            set.add(p4);
            for (Person1 person1 : set) {
                System.out.println(person1);
            }
    //        System.out.println(p1.hashCode());
    //        System.out.println(p2.hashCode());
    //        System.out.println(p3.hashCode());
    //        System.out.println(p4.hashCode());
    
        }
    
    }
    
    class Person1 {
        private String name;
        private int age;
    
        public Person1(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public Person1() {
        }
    
        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 "Person1{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person1 person1 = (Person1) o;
            return age == person1.age && Objects.equals(name, person1.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }
    

  • 自定义对象存储HashSet去重的步骤

    • 类中必须重写hashCode()和equals()方法

    • hashCode():属性相同的对象返回值必须相同,属性不同的返回值尽量不同(提高效率)

    • equals():属性相同返回true,属性不同返回false,返回false的时候存储到集合

    • 可使用编译器直接重写以上2个方法。

5.4 LinkedHashSet

  • 是HashSet的一个子类,继承了HashSet,与HashSet保证元素唯一的原理相同。

  • 底层实现是哈希表(数组+链表/红黑树)+链表。比HashSet多一个链表,负责记录元素的存储顺序,保证元素有序。

  • 将每个元素在存储的时候,都记录了前后元素的地址,就是存储在哈希表之外的链表中

  • 效果:

    • 可以根据存储元素的顺序,将元素取出

  • 应用:

    • 既需要保证元素的唯一,又需要保证原来的顺序,就可以考虑LinkedHashSet类型

  • 示例代码

  • import java.util.LinkedHashSet;
    
    /**
     * LinkedHashSet
     */
    public class Simple14 {
    
        public static void main(String[] args) {
            LinkedHashSet<String> lhs = new LinkedHashSet<>();
            lhs.add("abc");
            lhs.add("abc");
            lhs.add("abc");
    
            lhs.add("xyz");
            lhs.add("xyz");
    
            lhs.add("qq");
    
            lhs.add("123");
            lhs.add("123");
            lhs.add("123");
            System.out.println(lhs);
            [abc, xyz qq 123]
        }
    }

5.5 TreeSet

  • TreeSet 的底层实现方式为红黑树

    image-20230208235020038

  • 使用 TreeSet,需要元素类型实现 Comparable 接口并重写 compareTo 方法,或者提供 Comparator。

    • TreeSet 会自动排序(自然顺序),因为红黑树本身就是一颗二叉查找树,但也是无序的(存与取的顺序不同)。

    • package com.collection;
      
      import java.util.TreeSet;
      
      /**
       * @author Petrel
       */
      public class Simple15 {
          public static void main(String[] args) {
      
      //        TreeSet<Integer> set = new TreeSet<>();
      //        set.add(123);
      //        set.add(789);
      //        set.add(456);
      //        set.add(123);
      //        System.out.println(set);
              TreeSet<Person2> person = new TreeSet<>();
              person.add(new Person2("zhangsan", 16));
              person.add(new Person2("zhangsan", 18));
              person.add(new Person2("lisi", 23));
              person.add(new Person2("wangwu", 35));
      
              System.out.println(person);
      
          }
      }
      
      class Person2 implements Comparable<Person2> {
          private String name;
          private int age;
      
          public Person2(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public Person2() {
          }
      
          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 "Person2{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      
      
          @Override
          public int compareTo(Person2 o) {
              return this.name.compareTo(o.name);
          }
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gao_xu_sheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值