11.集合框架详解

image-20210224152227082

image-20210308221220743

集合

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

源码

img

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值