集合

集合

Collection

 

List

  • 有序,有下标,元素可以重复

 

实现类

  • ArrayList

数组结构实现,查询快,增删慢(必须开辟连续的空间)

jdk1.2版本,运行效率快,线程不安全

  • Vector

数组结构实现,查询快,增删慢

jdk1.0版本,运行效率慢,线程安全

  • LinkedList

链表结构实现,查询慢,增删快(无需开辟连续的空间)

jdk1.2版本,运行效率快,线程不安全

 

为什么ArrayList查询效率高,删除效率慢

ArrayLIst查询效率高:ArrayLIst是连续存放元素的,找到第一个元素的首地址,再加上每个元素的占据的字节大小就能定位到对应的元素。

LinkedList插入删除效率高。因为执行插入删除操作时,只需要操作引用即可,元素不需要移动元素,他们分布在内存的不同地方,通过引用来互相关联起来。而ArrayLIst需要移动元素,故效率低。

ArrayList

没有向集合添加任何元素的时候,容量为0, 第一次add数据的时候,初始容量就是10,然后按照1.5倍扩容(10->15->22->...)

遍历(迭代器)

ListIterator

  • 迭代器可以从前往后,也可以从后往前

public static void main(String[] args) {
   List<Integer> list = new ArrayList<>();
   list.add(10);
   list.add(20);
   list.add(30);
   list.add(40);
   list.add(50);
   list.add(60);
   ListIterator<Integer> integerListIterator = list.listIterator();
   System.out.println("ListIterator从前往后遍历---》");
   while (integerListIterator.hasNext()) {
       System.out.println(integerListIterator.nextIndex()+"======="+integerListIterator.next());
  }
   System.out.println("ListIterator从后往前遍历---》");
   while (integerListIterator.hasPrevious()) {
       System.out.println(integerListIterator.previousIndex()+"======="+integerListIterator.previous());
  }
}

输出

ListIterator从前往后遍历---》
0=======10
1=======20
2=======30
3=======40
4=======50
5=======60
ListIterator从后往前遍历---》
5=======60
4=======50
3=======40
2=======30
1=======20
0=======10

 

基本类型,自助装箱

 

subList

  • 返回子集合

public static void main(String[] args) {
   List<Integer> list = new ArrayList<>();
   list.add(10);
   list.add(20);
   list.add(30);
   list.add(40);
   list.add(50);
   list.add(60);
   List<Integer> subList = list.subList(0, 3);
   //下面打印 [10, 20, 30]
   System.out.println(subList.toString());
}

 

remove

源码

public boolean remove(Object o) {
   if (o == null) {
       for (int index = 0; index < size; index++)
           if (elementData[index] == null) {
               fastRemove(index);
               return true;
          }
  } else {
       for (int index = 0; index < size; index++)
           //这里比较的是地址,所以删除对象的时候,只比较值的话,需要重写equal和hashCode
           if (o.equals(elementData[index])) {
               fastRemove(index);
               return true;
          }
  }
   return false;
}

public boolean equals(Object obj) {
   return (this == obj);
}

重写Student后,就可以通过对象删除了 list.remove(new Student("张三", 3));

public class Student {
   private String name;
   private int age;

   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 boolean equals(Object o) {
       if (this == o) {
           return true;
      }
       if (o == null) {
           return false;
      }
       if (o instanceof Student) {
           Student student = (Student) o;
           return this.age == student.age && Objects.equals(this.name, student.name);
      } else {
           return false;
      }
  }

   @Override
   public int hashCode() {
       return Objects.hash(name, age);
  }

}
public static void main(String[] args) {
   List<Student> list = new ArrayList<>();
   Student s1 = new Student("张三", 3);
   Student s2 = new Student("李四", 4);
   Student s3 = new Student("王五", 5);
   list.add(s1);
   list.add(s2);
   list.add(s3);
   System.out.println(list.toString());
   //删除
   list.remove(new Student("张三", 3));
   System.out.println("删除后(已经重写了Student的equal和hashCode)" + list.toString());
}

输出

[Student{name='张三', age=3}, Student{name='李四', age=4}, Student{name='王五', age=5}]
删除后(已经重写了Student的equal和hashCode)[Student{name='李四', age=4}, Student{name='王五', age=5}]

ArrayList部分源码

public class ArrayList<E> extends AbstractList<E>
       implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
   
   private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
   //默认初始容量
   private static final int DEFAULT_CAPACITY = 10;
   //实际元素的大小
   private int size;
   //存放元素的数组
   transient Object[] elementData;

public ArrayList() {
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  }
   
   public boolean add(E e) {
       ensureCapacityInternal(size + 1);  // Increments modCount!!
       elementData[size++] = e;
       return true;
  }
   
   private void ensureCapacityInternal(int minCapacity) {
       ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  }
   
   private static int calculateCapacity(Object[] elementData, int minCapacity) {
       //没有向集合添加任何元素的时候,容量为0, 第一次add数据的时候,初始容量就是10,然后按照1.5倍扩容(10->15->22->...)
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
           return Math.max(DEFAULT_CAPACITY, minCapacity);
      }
       return minCapacity;
  }
   
   private void ensureExplicitCapacity(int minCapacity) {
       modCount++;
       // overflow-conscious code
       if (minCapacity - elementData.length > 0)
           grow(minCapacity);
  }
   
   /**
   *核心代码
   */
   private void grow(int minCapacity) {
       // overflow-conscious code
       int oldCapacity = elementData.length;
       int newCapacity = oldCapacity + (oldCapacity >> 1);
       if (newCapacity - minCapacity < 0)
           newCapacity = minCapacity;
       if (newCapacity - MAX_ARRAY_SIZE > 0)
           newCapacity = hugeCapacity(minCapacity);
       // minCapacity is usually close to size, so this is a win:
       elementData = Arrays.copyOf(elementData, newCapacity);
  }

}

 

Vector

public static void main(String[] args) {
   Vector<String> vector = new Vector<>();
   vector.add("A");
   vector.add("B");
   vector.add("C");
   vector.add("D");
   vector.add("E");
   System.out.println(vector);
   //遍历1
   Iterator<String> iterator = vector.iterator();
   while (iterator.hasNext()) {
       System.out.print(iterator.next() + "\t");
  }
   System.out.println();
   //遍历2 枚举器
   Enumeration<String> elements = vector.elements();
   while (elements.hasMoreElements()) {
       System.out.print(elements.nextElement() + "\t");
  }
}

 

LinkedList

双向链表

public static void main(String[] args) {
   LinkedList<Student> linkedList = new LinkedList<>();
   Student s1 = new Student("张三",3);
   Student s2 = new Student("李四",4);
   Student s3 = new Student("王五",5);
   Student s4 = new Student("赵流六",6);
   linkedList.add(s1);
   linkedList.add(s2);
   linkedList.add(s3);
   linkedList.add(s4);
   System.out.println(linkedList);
   System.out.println("=====遍历:增强型for循环=======");
   for (Student student : linkedList) {
       System.out.println(student.toString());
  }
   System.out.println("=====遍历:迭代器=======");
   Iterator<Student> iterator = linkedList.iterator();
   while (iterator.hasNext()) {
       System.out.println(iterator.next());
  }
}

源码

public class LinkedList<E>
   extends AbstractSequentialList<E>
   implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
   //实际元素的大小
   transient int size = 0;
   //链表头节点
   transient Node<E> first;
   //链表尾节点
   transient Node<E> last;
   //修改次数
   protected transient int modCount = 0;
   /**
* 空参数的构造由于生成一个空链表 first = last = null
*/
   public LinkedList() {
  }
   
   
   public boolean add(E e) {
       linkLast(e);
       return true;
  }
   
   /**
    *核心代码
    */
   void linkLast(E e) {
       final Node<E> l = last;
       final Node<E> newNode = new Node<>(l, e, null);//当前节点的prev指向了上一个节点,第一次添加的时候prev节点为null
       last = newNode;//链表尾节点last指向当前节点
       if (l == null)
           first = newNode;//第一次添加的时候,头节点first指向了当前添加的节点
       else
           l.next = newNode;//上个节点的next指向了当前节点
       size++;
       modCount++;
  }
   
   private static class Node<E> {
       E item;
       Node<E> next;
       Node<E> prev;

       Node(Node<E> prev, E element, Node<E> next) {
           this.item = element;
           this.next = next;
           this.prev = prev;
      }
  }
}

 

Set

  • 特点:无序,无下标,元素不可以重复

 

HashSet

  • 存储接口:哈希表(数据+链表(单向链表)+红黑树)

  • 存储过程

    • 根据hashCode,计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步

    • 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表

public static void main(String[] args) {
   Set<Integer> set = new HashSet<>();
   set.add(3);
   set.add(4);
   set.add(1);
   set.add(2);
   System.out.println(set);
   System.out.println("====遍历====");
   Iterator<Integer> iterator = set.iterator();
   while (iterator.hasNext()) {
       System.out.println(iterator.next());
  }
}

重写hashCode和equal

源码分析

public class HashSet<E>
   extends AbstractSet<E>
   implements Set<E>, Cloneable, java.io.Serializable {
   //HashSet实际使用HashMap的key储存元素的,value = new Object()
   private transient HashMap<E,Object> map;
   
   private static final Object PRESENT = new Object();
   
   public HashSet() {
       map = new HashMap<>();
  }
   
   public boolean add(E e) {
       return map.put(e, PRESENT)==null;
  }
}

TreeSet

  • 基于排列顺序实现元素不重复

  • 实现了SortedSet接口,对集合元素自动排序

  • 元素对象的类型必须实现Comparable,指定排序规则

  • 通过compareTo方法确定是否为重复元素

  • 存储结构:红黑树

 

public class NewStudent implements Comparable<NewStudent> {
   private String name;
   private int age;

   public NewStudent(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 "NewStudent{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
  }

   @Override
   public int compareTo(NewStudent o) {
       int i = this.name.compareTo(o.name);
       int j = this.age - o.age;
       return i == 0 ? j : i;
  }
}

验证

public static void main(String[] args) {
   TreeSet<NewStudent> treeSet = new TreeSet<>();
   NewStudent s1 = new NewStudent("zhangsan",13);
   NewStudent s2 = new NewStudent("lisi",14);
   NewStudent s3 = new NewStudent("wangwu",15);
   NewStudent s4 = new NewStudent("zhaoliu",18);
   NewStudent s5 = new NewStudent("zhaoliu",17);
   //重复,添加不了
   //       NewStudent s6 = new NewStudent("zhaoliu",17);
   treeSet.add(s1);
   treeSet.add(s2);
   treeSet.add(s3);
   treeSet.add(s4);
   treeSet.add(s5);
   //       treeSet.add(s6);
   System.out.println(treeSet.size());
   System.out.println(treeSet);
}

Comparator接口

public static void main(String[] args) {
   TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>(){
       @Override
       public int compare(Student o1, Student o2) {
           int i = o1.getName().compareTo(o2.getName());
           int j = o1.getAge() - o2.getAge();
           return i == 0 ? j : i;
      }
  });
   //也可以简化一下,用lambda表达式
   /*TreeSet<Student> treeSet = new TreeSet<>((o1, o2) -> {
           int i = o1.getName().compareTo(o2.getName());
           int j = o1.getAge() - o2.getAge();
           return i == 0 ? j : i;
       });*/
   Student s1 = new Student("zhangsan",13);
   Student s2 = new Student("lisi",14);
   Student s3 = new Student("wangwu",15);
   Student s4 = new Student("zhaoliu",18);
   Student s5 = new Student("zhaoliu",17);
   //重复,添加不了
   //       NewStudent s6 = new NewStudent("zhaoliu",17);
   treeSet.add(s1);
   treeSet.add(s2);
   treeSet.add(s3);
   treeSet.add(s4);
   treeSet.add(s5);
   //       treeSet.add(s6);
   System.out.println(treeSet.size());
   System.out.println(treeSet);
}

源码

public class TreeSet<E> extends AbstractSet<E>
   implements NavigableSet<E>, Cloneable, java.io.Serializable {
   //java.util.NavigableMap 可以看api帮助文档
   private transient NavigableMap<E,Object> m;
   private static final Object PRESENT = new Object();
   
   public TreeSet(Comparator<? super E> comparator) {
       this(new TreeMap<>(comparator));
  }
   
   TreeSet(NavigableMap<E,Object> m) {
       this.m = m;
  }
   
   public boolean add(E e) {
       return m.put(e, PRESENT)==null;
  }
   
}

Map

  • 无序

  • 存储键值对

  • 键不能重复,值可以重复

实现类

  • HashMap

JDK1.2版本,线程不安全,运行效率快,允许null作为key或者value

  • HashTable(很少用)

JDK1.0版本,线程安全,运行效率慢,不允许null作为key或者value

  • Properties

HashTable的子类,要求key和value都是String。通常用于配置文件的读取

  • TreeMap

实现了SortedMap接口,可以对key自动排序

HashMap

  • 存储结构:哈希表(数组+链表+红黑树)

  • 使用key的hashCode和equals作为重复依据

原理文章

entrySet效率要高于keySet

public static void main(String[] args) {
   Map<String, Integer> map = new HashMap<>(16);
   map.put("A", 1);
   map.put("B", 2);
   map.put("C", 3);
   map.put("D", 1);
   map.put("E", 1);
   map.put("F", 1);
   map.put("G", 1);
   map.put("H", 1);
   System.out.println(map);
   System.out.println("========entrySet=========");

   Set<Map.Entry<String, Integer>> entries = map.entrySet();
   long start = System.currentTimeMillis();
   for (Map.Entry<String, Integer> entry : entries) {
       System.out.println(entry.getKey() + "=======" + entry.getValue());
  }
   long end = System.currentTimeMillis();
   System.out.println("entrySet用时:" + (end - start));
   System.out.println("========keySet=========");
   Set<String> strings = map.keySet();
   for (String string : strings) {
       System.out.println(string + "=======" + map.get(string));
  }
   long end2 = System.currentTimeMillis();
   System.out.println("keySet用时:" + (end2 - end));
}

源码

public class HashMap<K,V> extends AbstractMap<K,V>
   implements Map<K,V>, Cloneable, Serializable {
   //默认初始容量 16
   static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
   //最大容量
   static final int MAXIMUM_CAPACITY = 1 << 30;
   //默认的加载因子
   static final float DEFAULT_LOAD_FACTOR = 0.75f;
   //树化阀值
   static final int TREEIFY_THRESHOLD = 8;
   //树还原链表阀值 当链表长度小于6的时候,红黑树会还原为链表
   static final int UNTREEIFY_THRESHOLD = 6;
   //最小树化容量 jdk1.8 当链表长度大于8 并且数组元素个数>=64,链表会转化为红黑树
   static final int MIN_TREEIFY_CAPACITY = 64;
   //数组+链表(单向链表,next)
   transient Node<K,V>[] table;
   //键值对的数量
   transient int size;
   //加载因子
   final float loadFactor;
   //下一次扩容的阀值
   int threshold;
   
   //节点(键值对),单向链表
   static class Node<K,V> implements Map.Entry<K,V> {
       final int hash;
       final K key;
       V value;
       Node<K,V> next;
       //...
  }
}

无参构造方法

    public HashMap() {
       //加载因子为默认加载因子0.75f
       this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
  }

有参构造方法


   public HashMap(int initialCapacity) {
       this(initialCapacity, DEFAULT_LOAD_FACTOR);
  }

public HashMap(int initialCapacity, float loadFactor) {
       //校验传入的容量
       if (initialCapacity < 0)
           throw new IllegalArgumentException("Illegal initial capacity: " +
                                              initialCapacity);
       //传入的容量大于最大容量,就等于最大容量(2的30次方)
       if (initialCapacity > MAXIMUM_CAPACITY)
           initialCapacity = MAXIMUM_CAPACITY;
       //校验加载因子
       if (loadFactor <= 0 || Float.isNaN(loadFactor))
           throw new IllegalArgumentException("Illegal load factor: " +
                                              loadFactor);
       this.loadFactor = loadFactor;
       this.threshold = tableSizeFor(initialCapacity);
  }


   static final int tableSizeFor(int cap) {
       int n = cap - 1;
       n |= n >>> 1;
       n |= n >>> 2;
       n |= n >>> 4;
       n |= n >>> 8;
       n |= n >>> 16;
       return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  }

put

    public V put(K key, V value) {
       return putVal(hash(key), key, value, false, true);
  }

//计算key的hash值
static final int hash(Object key) {
       int h;
       return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  }

//put值
   final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                  boolean evict) {
       Node<K,V>[] tab; Node<K,V> p; int n, i;
       if ((tab = table) == null || (n = tab.length) == 0)
           n = (tab = resize()).length;
       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;
  }


   final Node<K,V>[] resize() {
       Node<K,V>[] oldTab = table;
       int oldCap = (oldTab == null) ? 0 : oldTab.length;
       int oldThr = threshold;
       int newCap, newThr = 0;
       if (oldCap > 0) {
           if (oldCap >= MAXIMUM_CAPACITY) {
               threshold = Integer.MAX_VALUE;
               return oldTab;
          }
           else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                    oldCap >= DEFAULT_INITIAL_CAPACITY)
               newThr = oldThr << 1; // double threshold
      }
       else if (oldThr > 0) // initial capacity was placed in threshold
           newCap = oldThr;
       else {               // zero initial threshold signifies using defaults
           newCap = DEFAULT_INITIAL_CAPACITY;
           newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
      }
       if (newThr == 0) {
           float ft = (float)newCap * loadFactor;
           newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                    (int)ft : Integer.MAX_VALUE);
      }
       threshold = newThr;
       @SuppressWarnings({"rawtypes","unchecked"})
       Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
       table = newTab;
       if (oldTab != null) {
           for (int j = 0; j < oldCap; ++j) {
               Node<K,V> e;
               if ((e = oldTab[j]) != null) {
                   oldTab[j] = null;
                   if (e.next == null)
                       newTab[e.hash & (newCap - 1)] = e;
                   else if (e instanceof TreeNode)
                      ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                   else { // preserve order
                       Node<K,V> loHead = null, loTail = null;
                       Node<K,V> hiHead = null, hiTail = null;
                       Node<K,V> next;
                       do {
                           next = e.next;
                           if ((e.hash & oldCap) == 0) {
                               if (loTail == null)
                                   loHead = e;
                               else
                                   loTail.next = e;
                               loTail = e;
                          }
                           else {
                               if (hiTail == null)
                                   hiHead = e;
                               else
                                   hiTail.next = e;
                               hiTail = e;
                          }
                      } while ((e = next) != null);
                       if (loTail != null) {
                           loTail.next = null;
                           newTab[j] = loHead;
                      }
                       if (hiTail != null) {
                           hiTail.next = null;
                           newTab[j + oldCap] = hiHead;
                      }
                  }
              }
          }
      }
       return newTab;
  }

 

总结

  • HashMap刚刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16

  • 当元素个数大于阀值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数

  • jdk1.8 当单个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率

  • jdk1.8 当链表长度小于6时,调整为链表

  • jdk1.8以前,链表是头插入,jdk1.8以后是尾插入

 

TreeMap

  • 存储结构:红黑树

public class Student implements Comparable<Student> {
   private String name;
   private int age;

   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 boolean equals(Object o) {
       if (this == o) {
           return true;
      }
       if (o == null) {
           return false;
      }
       if (o instanceof Student) {
           Student student = (Student) o;
           return this.age == student.age && Objects.equals(this.name, student.name);
      } else {
           return false;
      }
  }

   @Override
   public int hashCode() {
       return Objects.hash(name, age);
  }


   @Override
   public int compareTo(Student o) {
       int i = this.name.compareTo(o.name);
       int j = this.age - o.age;
       return i == 0 ? j : i;
  }
}

测试类

public static void main(String[] args) {
   Map<Student, String> map = new TreeMap<>();
   //或者自定义比较器
   /*Map<Student, String> map = new TreeMap<>((o1, o2) -> {
           int i = o1.getName().compareTo(o2.getName());
           int j = o1.getAge() - o2.getAge();
           return i == 0 ? j : i;
       });*/
   Student s1 = new Student("zhangsan", 12);
   Student s2 = new Student("lisi", 18);
   Student s3 = new Student("wangwu", 20);
   Student s4 = new Student("zhaoliu", 8);
   map.put(s1, "北京");
   map.put(s2, "南京");
   map.put(s3, "天津");
   map.put(s4, "深圳");
   //       map.put(new Student("zhaoliu", 8), "广州");
   System.out.println(map.size());
   System.out.println(map);
}

源码

public class TreeMap<K,V>
   extends AbstractMap<K,V>
   implements NavigableMap<K,V>, Cloneable, java.io.Serializable {
   //比较器
   private final Comparator<? super K> comparator;
   //根节点
   private transient Entry<K,V> root;
   //键值对数量
   private transient int size = 0;
   //修改次数
   private transient int modCount = 0;
   //无参构造方法
   public TreeMap() {
       comparator = null;
  }
   //有参构造方法,自定义比较器
   public TreeMap(Comparator<? super K> comparator) {
       this.comparator = comparator;
  }
   //put方法
   public V put(K key, V value) {
       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;
      }
       int cmp;
       Entry<K,V> parent;
       // split comparator and comparable paths
       Comparator<? super K> cpr = comparator;
       if (cpr != null) {
           do {
               parent = t;
               cmp = cpr.compare(key, t.key);
               if (cmp < 0)
                   t = t.left;
               else if (cmp > 0)
                   t = t.right;
               else
                   return t.setValue(value);
          } while (t != null);
      }
       else {
           if (key == null)
               throw new NullPointerException();
           @SuppressWarnings("unchecked")
               Comparable<? super K> k = (Comparable<? super K>) key;
           do {
               parent = t;
               cmp = k.compareTo(t.key);
               if (cmp < 0)
                   t = t.left;
               else if (cmp > 0)
                   t = t.right;
               else
                   return t.setValue(value);
          } while (t != null);
      }
       Entry<K,V> e = new Entry<>(key, value, parent);
       if (cmp < 0)
           parent.left = e;
       else
           parent.right = e;
       fixAfterInsertion(e);
       size++;
       modCount++;
       return null;
  }
}

 

泛型

  • 泛型类

  • 泛型接口

  • 泛型方法

泛型类

public class GenericDemo<T> {
   /**
    * 泛型成员变量
    */
   private T t;

   /**
    * 泛型返回值
    *
    * @return
    */
   public T getT() {
       return t;
  }

   /**
    * 泛型形参
    *
    * @param t
    */
   public void setT(T t) {
       this.t = t;
  }
}

泛型接口

public interface GenericInterfaceDemo<T> {
   T get(T t);
}

实现接口的时候指定泛型

public class GenericInterfaceImplDemo implements GenericInterfaceDemo<String> {
   @Override
   public String get(String s) {
       return s;
  }
}

让实例化对象的时候指定泛型

public class GenericInterfaceImplDemo2<T> implements GenericInterfaceDemo<T> {
   @Override
   public T get(T t) {
       return t;
  }
}

验证

public static void main(String[] args) {
   GenericInterfaceImplDemo genericInterfaceImplDemo = new GenericInterfaceImplDemo();
   System.out.println(genericInterfaceImplDemo.get("dsd"));

   GenericInterfaceImplDemo2<Integer> genericInterfaceImplDemo2 = new GenericInterfaceImplDemo2();
   System.out.println(genericInterfaceImplDemo2.get(123));
//下面是验证泛型方法
   GenericMethodDemo demo = new GenericMethodDemo();
   Student s1 = new Student("张三", 3);
   System.out.println(demo.get(s1));
}

泛型方法

public class GenericMethodDemo {
   /**
    * 语法:<T> 方法返回值     就是在方法的返回值之前加上<T>
    * @param t
    * @param <T>
    * @return
    */
   public <T> T get(T t) {
       return t;
  }
}

 

Collections工具类

public static void main(String[] args) {
   List<Integer> list = new ArrayList<>();
   list.add(13);
   list.add(50);
   list.add(1);
   list.add(3);
   list.add(10);
   list.add(8);
   System.out.println("原集合"+list);
   Collections.sort(list);
   System.out.println("排序后"+list);
   System.out.println("二分查找"+Collections.binarySearch(list, 13));
   List desList = new ArrayList();
   //这里不能忽略,不然复制失败
   for (Integer integer : list) {
       desList.add(0);
  }
   Collections.copy(desList, list);
   System.out.println("复制数组"+desList);
   Collections.reverse(list);
   System.out.println("反转"+list);
   Collections.shuffle(list);
   System.out.println("打乱"+list);
   //补充,list转数组
   System.out.println("====list转数组======");
   Integer[] integers = list.toArray(new Integer[list.size()]);
   System.out.println(integers.length);
   System.out.println(Arrays.toString(integers));
   //数组转list
   System.out.println("====数组转list======");
   //基本数据类型数组转成集合是,需要修改为包装类
   Integer[] ints = {0,9,4,2,1,8};
   List<Integer> numberList = Arrays.asList(ints);
   //集合是一个受限集合,不能添加和删除
   //numberList.add(3);
   //numberList.remove(0);
   System.out.println(numberList);
}
 
posted @ 2022-06-29 14:17  jhw-  阅读(7)  评论(0)    收藏  举报