早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组。
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
package com.hspedu.collection_; import java.util.ArrayList; import java.util.HashMap; /** * @author 山河与you皆无恙 */ public class Collection_ { @SuppressWarnings("all") public static void main(String[] args) { //1.集合主要是两组(单列集合,双列集合) //2.Collection 接口有两个重要的子接口 List Set,他们的实现子类都是单列集合 //3.Map 接口的实现子类是 双列集合,存放的 K-V //4.两张图很重要,需要记住 //Collection //Map ArrayList arrayList = new ArrayList(); arrayList.add("jack"); arrayList.add("tom"); HashMap hashMap = new HashMap(); hashMap.put("NO1","北京"); hashMap.put("NO2","上海"); } }
package com.hspedu.collection_; import java.util.ArrayList; import java.util.List; /** * @author 山河与you皆无恙 */ public class CollectionMethod { @SuppressWarnings("all") public static void main(String[] args) { List list = new ArrayList(); // add:添加某个元素 list.add("jack"); list.add(10);//list.add(new Integer(10)) list.add(true); System.out.println("List"+list); // remove:删除指定元素 // list.remove(0);//删除第一个元素 list.remove(true); // cotains:查找元素是否存在 System.out.println(list.contains("jack")); // size:获取元素个数 System.out.println(list.size()); // isEmpty:判断元素是否为空 System.out.println(list.isEmpty()); // clear:清空 list.clear(); System.out.println("List"+list); // addall: ArrayList list2 = new ArrayList(); list2.add("红楼梦"); list2.add("三国演义"); list.addAll(list2); System.out.println("List"+list); // containsall:查找多个元素是否存在 System.out.println(list.containsAll(list2));//true list.add("聊斋"); // removeall:删除多个元素 list.removeAll(list2); System.out.println("List"+list); // 说明:以ArrayList实现来演示 } }
package com.hspedu.collection_; import java.util.ArrayList; import java.util.Collection; /** * @author 山河与you皆无恙 */ public class CollectionFor { @SuppressWarnings("all") public static void main(String[] args) { Collection col = new ArrayList(); col.add(new Book("三国演义","罗贯中",10.1)); col.add(new Book("小李飞刀","古龙",10.1)); col.add(new Book("红楼梦","曹雪芹",34.6)); //1.使用增强for,在Collection集合 //2.增强for,底层仍然是迭代器 //3.增强for可以理解为简化版的迭代器遍历 //4.快捷键 I // for (Object book:col) { // System.out.println("Book"+book); // } for (Object o :col) { System.out.println("Book"+o); } } }
package com.hspedu.collection_; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * @author 山河与you皆无恙 */ public class CollectionIterator { @SuppressWarnings("all") public static void main(String[] args) { Collection col = new ArrayList(); col.add(new Book("三国演义","罗贯中",10.1)); col.add(new Book("小李飞刀","古龙",10.1)); col.add(new Book("红楼梦","曹雪芹",34.6)); //1.遍历集合 System.out.println("col="+col); //先得到 Iterator的迭代器 Iterator iterator = col.iterator(); //2.使用while循环遍历 // while (iterator.hasNext()) {//判断是否还有数据 // //返回下一个元素,类型是 Object // Object obj = iterator.next(); // System.out.println("obj"+obj); // // } //快捷键生成 while循环遍历=》itit+enter(即回车) //显示所有快捷键的快捷键 ctrl+j while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println("obj"+obj); } //当退出while以后,这时iterator迭代器指向最后的元素 //iterator.next();//NoSuchElmentException //如果需要再次遍历,需要重置我们的迭代器 iterator = col.iterator(); System.out.println("=======第二次遍历======="); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println("obj"+obj); } } } class Book{ private String name; private String author; private double price; public Book(String name, String author, double price) { this.name = name; this.author = author; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", author='" + author + '\'' + ", price=" + price + '}'; } }
java.util.Collections 是一个包装类。它包含有各种有关集合操作的 静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
package com.hspedu.collections_; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class Collections_ { //创建 ArrayList 集合 用于测试 public static void main(String[] args) { List list = new ArrayList(); list.add("tom"); list.add("smith"); list.add("king"); list.add("milan"); System.out.println("list= "+list); //reverse(list):反转list中的元素的是顺序 Collections.reverse(list); //shuffle(list):对list中的元素进行随机排序 System.out.println("list= "+list); // for (int i = 0; i <5 ; i++) { // Collections.shuffle(list); // System.out.println("list= "+list); // } //sort(list):对集合list中的元素自然排序 Collections.sort(list); System.out.println("list= "+list); //按照字符串长度比较 Collections.sort(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).length()-((String)o2).length(); } }); System.out.println("字符串长度大小= "+list); //将指定 list 集合中的i 处元素和j处元素进行交换 //wap(list,1,2) Collections.swap(list,1,2); System.out.println("交换后= "+list); //Object max(Collectionn):根据元素自然排序,返回给定集合中的最大元素 System.out.println("自然排序最大元素="+Collections.max(list)); //比如返回最大的元素 //根据Comparator指定的顺序,返回给定集合中的最大元素 Object maxObject = Collections.max(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).length()-((String)o2).length(); } }); System.out.println("长度最大的元素="+maxObject); //int frequency(Collection,Object)) 返回指定集合中指定元素的出现次数 System.out.println("tom出现的次数="+Collections.frequency(list,"tom")); //void copy(List dest,List src) 将src中的内容复制到dest中 ArrayList dest = new ArrayList(); //为了完成完整拷贝,先给 dest 赋值,大小和 list,size()大小一样 for (int i = 0; i <list.size() ; i++) { dest.add(""); } //拷贝 Collections.copy(dest,list); System.out.println("dest="+dest); //boolearn replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值 boolean b = Collections.replaceAll(list, "tom", "汤姆"); System.out.println("list替换后= "+list); } }
该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。
package com.hspedu.list_; import java.util.ArrayList; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class ArrayListSource { public static void main(String[] args) { //注意,注意,注意,idea 默认情况下, Debug 显示的数据是简化后的,如果希望看到完整的数据需要做设置 //使用无参构造器创建 ArrayList 对象 //ArrayList list = new ArrayList(); ArrayList list = new ArrayList(8); //使用for给list集合添加1—10数据 for (int i = 0; i <=10 ; i++) { list.add(i); } //用for给list集合添加11-15 // 数据 for (int i = 11; i <15 ; i++) { list.add(i); } list.add(100); list.add(200); list.add(null); } }
该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:
List list=Collections.synchronizedList(newLinkedList(…));
LinkedList 查找效率低。
package com.hspedu.list_; import java.util.Iterator; import java.util.LinkedList; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class LinkedListCRUD { public static void main(String[] args) { LinkedList linkedList = new LinkedList(); linkedList.add(1); linkedList.add(2); linkedList.add(3); System.out.println("linkedList"+linkedList); //演示一个删除结点的 linkedList.remove();//这里默认删除的是第一个结点 System.out.println("linkedList"+linkedList); //修改某个结点对象 linkedList.set(1,999); System.out.println("linkedList"+linkedList); //得到某个结点的对象 //get(1)是得到双向链表的第二个对象 Object o = linkedList.get(1); System.out.println(0); //因为linkedList是实现了list接口方式,遍历方式 System.out.println("=============linedList遍历迭代器============"); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next); } System.out.println("=============linedList遍历增强for============"); for (Object o1 :linkedList) { System.out.println("o1=0"+o1); } System.out.println("=============linedList遍历普通for============"); for (int i = 0; i <linkedList.size() ; i++) { System.out.println(linkedList.get(i)); } /*//1.LinkedList linkedList = new LinkedList(); public LinkedList {} 2.这时LinkedList的属性 first =null last =null 3. 执行、添加 public boolean add(E e) { linkLast(e); return true; } 4. void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } */ /* linkedList.remove();//这里默认删除的是第一个结点 1.执行 public E remove() { return removeFirst(); } 2.执行 public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } 3.执行 unlinkFirst 将f指向的第一个结点拿掉 private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; } */ } }
该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。
package com.hspedu.set_; import java.util.HashSet; import java.util.Set; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class HashSet_ { public static void main(String[] args) { /* 1.构造器走的源码 2.HashSet 可以存放null 但是只能有一个null,即元素不能重复 */ Set hashSet = new HashSet(); hashSet.add(null); hashSet.add(null); System.out.println("hashSet= "+hashSet); } }
package com.hspedu.set_; import java.util.HashSet; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class HashSetSource { public static void main(String[] args) { HashSet hashSet = new HashSet(); hashSet.add("java"); hashSet.add("php"); hashSet.add("java"); System.out.println("set="+hashSet); /* 1.执行HashSet() public HashSet() { map = new HashMap<>(); } 2.执行add() public boolean add(E e) {//e="java" return map.put(e, PRESENT)==null;//(static) PRESENT = new Object(); } 3.执行put(),该方法会执行 hash(key)得到 key 对应的 hash 值 算法(h = key.hashCode()) ^ (h >>> 16) public V put(K key, V value) {//key="java" value = PRESENT 共享 return putVal(hash(key), key, value, false, true); } 4.执行 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i;//定义了辅助变量 //table 就是 HashMap 的一个数组,类型是 Node[] //if语句表示如果当前 table 是null,或者大小=0 //就是第一次扩容到16个空间 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //(1)根据key 得到hash 去计算该key应该存放到索引表的哪个索引位置 //并把这个位置的对象赋给p //(2)判断 p 是否为null //(2.1)如果 p 为null,表示还没有存放元素,就创建一个 Node(Key = "java",value = PRESENT) //(2.2)就放在该位置tab[i] = newNode(hash, key, value, null) if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { //一个开发技巧提示,:在创建局部变量(辅助变量)的时候,在创建 Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; } */ } }
该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。
package com.hspedu.list_; import java.util.Vector; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class Vector_ { public static void main(String[] args) { // Vector vector = new Vector(); Vector vector = new Vector(8); for (int i = 0; i <=10; i++) { vector.add(i); } /* //1.Vector底层 public Vector() { this(10); } //2.Vector.add() //2.1添加数据到Vector集合 public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } 补充:如果是Vector vector = new Vector(8) 走的方法 public Vector(int initialCapacity) { this(initialCapacity, 0); } //确定是否需要扩容 条件:minCapacity - elementData.length > 0 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //如果需要的数组大小不够用,就扩容,扩容的算法,就是扩容2倍 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } */ } }
Map 接口存储一组键值对象,提供key(键)到value(值)的映射。
package com.hspedu.map_; import java.util.HashMap; import java.util.Map; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class Map_ { public static void main(String[] args) { //Map实现类的特点,使用实现类HashMap //1.Map与Collection并列存在,用于保存具有映射关系的数据:key-value(双列元素) //2.Map 中的 key 和 value 可以是任何类型的数据,会封装到 HashMap$Node 对象中 //3.Map 中的 key 不允许重复,原因和 HashSet 一样,前面源码已经分析 //4.Map 中的 value 可以重复 //5.注意:Map 中的 key 可以为null,value也可以为null, Map 中的key为null只能有一个,value为null可以多个 //6.常用String类作为Map的key Map map = new HashMap(); map.put("no1","韩顺平");//k-v map.put("no2","张无忌");//k-v map.put("no1","张三丰");//k-v 当有相同的 k,就等价于替换。 map.put("no3","张三丰");//k-v map.put(null,null);//k-v map.put(null,"abc");//k-v 等价替换 map.put("no4",null);//k-v map.put("no5",null);//k-v System.out.println("map="+map); //通过get方法 传入 key,会返回对应的 value System.out.println(map.get("no2")); } }
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
package com.hspedu.map_; import java.util.HashMap; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class HashMapSource1 { public static void main(String[] args) { HashMap hashMap = new HashMap(); hashMap.put("java",10); hashMap.put("php",10); hashMap.put("java",20); System.out.println("hashMap="+hashMap); /* 1.执行构造器 new HashMap 初始化加载因子 loadFactor HashMap$Node[] table = null public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } 2.执行put 调用Hash方法,计算 key的hash值 (h = key.hashCode()) ^ (h >>> 16) public V put(K key, V value) {//key="java" value =10 return putVal(hash(key), key, value, false, true); } 3.执行 putVal final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; //如果底层的table数组为null,或者 length = 0就扩容到16 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //取出hash值对应的table索引位置的Node,如果为null,就直接把加入的k-v //,创建成一个Node,加入该位置即可 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k;//辅助变量 //如果 table 的索引位置的key的hash值和新的key的hash值相同 //并满足(table 现有结点的key和准备添加的key是同一个对象 || equals 返回真) //就认为不能加入行的key if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode)//如果当前的table的已有的 Node 是红黑树,就按照红黑树的方式处理 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else {//如果找到的结点,后面是链表,就循环比较 for (int binCount = 0; ; ++binCount) {//死循环 if ((e = p.next) == null) {//如果整个链表没有和它相同,就加到链表的最后, p.next = newNode(hash, key, value, null); //加入后 就判断当前链表的个数,是否已经到8个,后 //就调用 treeifyBin 方法进行红黑树转换 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash &&//如果在循环比较过程中,发现有相同,就 break,就只是替换 value ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value;//替换 key 对应的值 afterNodeAccess(e); return oldValue; } } ++modCount;//没增加一个 Node,就size++ if (++size > threshold)//如size>临界值(12-24-48----),就扩容 resize(); afterNodeInsertion(evict); return null; } 5.关于树化(转成红黑树) //如果 table 为 null 或者大小还没有到 64 暂时不树化,而是进行扩容 //否则才会真正的树化->剪枝 final void treeifyBin(Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e; if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); */ } }
package com.hspedu.map_; import java.util.*; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class MapFor { public static void main(String[] args) { Map map = new HashMap(); map.put("邓超",new Book("",100));//ok map.put("邓超","孙俪");//替换 map.put("王宝强","马蓉");//ok map.put("宋喆","马蓉");//ok map.put("刘令博",null);//ok map.put(null,"刘亦菲");//ok map.put("鹿晗","关晓彤");//ok System.out.println("map= "+map); //1.第一组:先取出所有的key,通过key取出对应的value //(1)增强for System.out.println("================第一种方式================"); Set keySet = map.keySet(); for (Object key : keySet) { System.out.println(key+"-"+map.get(key)); } System.out.println("================第二种方式================"); Iterator iterator = keySet.iterator(); while (iterator.hasNext()) { Object key = iterator.next(); System.out.println(key+"-"+map.get(key)); } //第二组:把所有的Values取出 Collection values = map.values(); //这里可以使用所有 Collection 的方法 //(1)增强for System.out.println("=============取出所有的value 增强for(第1种)=============="); for (Object value :values) { System.out.println(value); } //(2)迭代器 System.out.println("=============取出所有的value 迭代器(第2种)=============="); Iterator iterator2 = values.iterator(); while (iterator2.hasNext()) { Object value = iterator2.next(); System.out.println(value); } //第三组:通过EntreySet 来获取k—v System.out.println("=============使用EntrySet的for增强(第3种)=============="); Set entrySet = map.entrySet(); for (Object entry :entrySet) { Map.Entry m = (Map.Entry) entry; System.out.println(m.getKey()+"-"+m.getValue()); } //第四组:通过EntrySet的 迭代器来获取k—v System.out.println("=============使用EntrySet的 迭代器(第4种)=============="); Iterator iterator3 = entrySet.iterator(); while (iterator3.hasNext()) { Object entry = iterator3.next(); System.out.println(entry );//HashMap$Node->实现 Map.Entry(getKey,getValue) Map.Entry m = (Map.Entry) entry; System.out.println(m.getKey()+"-"+m.getValue()); } } }
继承了AbstractMap,并且使用一颗树。
package com.hspedu.map_; import java.util.Comparator; import java.util.TreeMap; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class TreeMap_ { public static void main(String[] args) { //使用默认的构造器创建TreeMap 是无序 //按照传入的 k(String)的大小进行排序 //TreeMap treeMap = new TreeMap(); TreeMap treeMap = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { //按照传入的 k(String)的大小进行排序 // return ((String) o1).compareTo((String) o2); //按照字符串长度进行比较 return ((String) o1).length()-((String) o2).length(); } }); treeMap.put("jack","杰克"); treeMap.put("tom","汤姆"); treeMap.put("kristina","克瑞斯提诺"); treeMap.put("smith","斯密斯"); System.out.println("treeMap="+treeMap); /* 1.构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性this.comparator public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } 2.调用put方法 2.1 第一次添加 把 K V封装到 Entry 对象,放入 root Entry<K,V> t = root; if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; } 2.2 以后添加 Comparator<? super K> cpr = comparator; if (cpr != null) { do {//遍历所有的key 给当前的key 找到适当的位置 parent = t; cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compare if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else//如果遍历过程中,发现准备添加key 和当前已有的 Key 相等,就不添加 return t.setValue(value); } while (t != null); } */ } }
该类实现了Set接口,可以实现排序等功能。
package com.hspedu.map_; import java.util.Comparator; import java.util.TreeSet; /** * @author 山河与you皆无恙 */ @SuppressWarnings({"all"}) public class TreeSet_ { public static void main(String[] args) { TreeSet treeSet = new TreeSet(new Comparator() { @Override public int compare(Object o1, Object o2) { //return ((String)o2).compareTo((String)o1); //按照长度大小比较 return ((String)o1).length()-((String)o2).length(); } }); //添加数据 treeSet.add("jack"); treeSet.add("tom"); treeSet.add("sp"); treeSet.add("a"); treeSet.add("abc");//加入不了 System.out.println("treeSet="+treeSet); /* 1.构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性this.comparator public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } 2.在调用 treeSet.add("tom"),会执行到 if (cpr != null) {//cpr就是我们的匿名内部类(对象) do { parent = t; //动态绑定到我们的匿名内部类对象compare cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else//如果相等,即返回0,这个key就没有加入 return t.setValue(value); } while (t != null); } */ } }
跟着老韩学习做的简要笔记
视频地址:https://www.bilibili.com/video/BV1YA411T76k?spm_id_from=333.999.0.0