Java 集合

1. 集合框架体系

Collection

Collection
List
Set
ArrayList
LinkedList
Vector
HashSet
LinkedHashSet
TreeSet

Map

Map
HashMap
HashTable
LinkedHashMap
Treemap
Properties

2. 集合关系图

Collection

image-20221016172606372

Map

image-20221016172315756

3. Collection

1. 方法

image-20221016190427788

2. 遍历

迭代器遍历

public class TestIterator {
    public static void main(String[] args) {
        Collection<Integer> col = new ArrayList<>();
        col.add(1);
        col.add(2);
        col.add(3);
        col.add(4);
        //使用迭代器遍历
        Iterator iterator = col.iterator();
        while(iterator.hasNext()){
            //返回下一个元素,类型是Object
            System.out.println(iterator.next());
        }
        //注意,当退出 while 循环后,这时 iterator 迭代器指向最后的元素
        //如果希望重新遍历,需要重置迭代器
        iterator = col.iterator();
        while(iterator.hasNext()){//第二次遍历
            //返回下一个元素,类型是Object
            System.out.println(iterator.next());
        }
    }
}

增强for循环

注意增强for循环底层依然是迭代器,增强for循环可以理解为一个简化版的迭代器

public class TestFor {

    public static void main(String[] args) {
        Collection<Integer> col = new ArrayList<>();
        col.add(1);
        col.add(2);
        col.add(3);
        col.add(4);

        //使用增强for循环
        //底层依然是迭代器
        for(Integer i : col){
            System.out.println(i);
        }

        //可以使用在数组
        int[] nums = {1,2,3,4,5};
        for(int i : nums){
            System.out.println(i);
        }
    }
}

4. List

  1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
  2. List 集合中的每个元素都有其对应的顺序索引,即支持索引。(底层是数组

1. 常用方法

  • void add(int index, Object ele):在index位置插入ele元素
  • boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
  • Object get(int index):获取指定index位置的元素
  • int indexOf(Object obj):返回obj在集合中首次出现的位置
  • int lastlndexOf(Object obj):返回obj在当前集合中末次出现的位置Object remove(int index):移除指定index位置的元素,并返回此元素
  • Object set(int index,Object ele):设置指定index位置的元素为ele相当于是替换.
  • List subList(int fromlndex, int tolndex):返回从fromlndex到tolndex位置的子集合(左闭右开

2. ArrayList(线程不安全)

注意事项

  • ArrayList 可以加入 null,并且多个
  • ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码,在多线程情况下,不建议使用ArrayList,举例如下
//下面是 ArrayList 的添加元素源码,可以看出并没有用synchronize方法修饰
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

扩容机制

  • ArrayList中维护了一个Object类型的数组elementData.
    • transient Object ] elernentData;//transient表示瞬间,短暂的,表示该属性不会被序列化
  • 当创建ArrayList对象时
    • 如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
    • 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍

add()源码分析

public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
    }

运行过程分析

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//创建一个空数组
}
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  //确定是否需要扩容
    elementData[size++] = e; //赋值
    return true;
}
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //看看是否为空数组
        //DEFAULT_CAPACITY: 10
        //minCapacity:1
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //确定minCapacity,第一次扩容为10
    }

    ensureExplicitCapacity(minCapacity);//明确是否扩容
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//记录集合被修改次数

    // overflow-conscious code
    if (minCapacity - elementData.length > 0) // 如果最小容量-当前数组容量大于零,即elementData 的大小不够
        grow(minCapacity);//真正扩容的方法
}
/*
	第一次newCapacity =10
	第二次及其以后,按照1.5倍扩容
*/
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);
}

有参构造器源码

//创造一个大小为 initialCapacity 的数组
public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

3. Vector(线程安全)

基本介绍

  • Vector类的定义说明

    public class Vector<E>
        extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
    
  • Vector底层也是一个对象数组,protected Object[] elementData;

  • Vector是线程同步的,即线程安全, Vector类的操作方法带有synchronized

    public synchronized E get(int index) {
            if (index >= elementCount)
                throw new ArrayIndexOutOfBoundsException(index);
    
            return elementData(index);
        }
    
  • 在开发中,需要线程同步安全时,考虑使用Vector

扩容机制

如果是无参,默认10,满后,按照2倍扩容;如果是指定大小,则每次直接按照2倍扩

//无参构造器
public Vector() {
        this(10);
}
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity]; //创建指定大小的数组
        this.capacityIncrement = capacityIncrement;
}
//扩容方法
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);
}

4. Vector和ArrayList的比较

底层结构版本线程安全(同步)效率扩容机制
ArrayList可变数组jdk1.2不安全,效率高有参构造器1.5倍;无参构造器:第一次是:10,第二次开始按照1.5倍扩容
Vector可变数组jdk1.0安全,效率不高如果是无参,默认10,满后,按照2倍扩容;如果是指定大小,则每次直接按照2倍扩

5. LinkedList(线程不安全)

基本介绍

  • LinkedList 底层实现了双向链表和双端队列特点
  • 可以添加任意元素(元素可以重复),包括null
  • 线程不安全,没有实现同步

底层结构

  • LinkedList 底层维护了一个双向链表.
  • LinkedList 中维护了两个属性 first 和 last 分别指向首节点和尾节点
  • 每个节点(Node对象),里面又维护了 prev、next、item 三个属性,其中通过 prev 指向前一个,通过 next 指向后一个节点。最终实现双向链表.
  • 所以 LinkedList 的元素的添加和删除,不是通过数组完成的,相对来说效率较高

源码解读

List<Integer> linkedList = new LinkedList<>();
linkedList.add(1);
linkedList.remove();//默认删除第一个元素
System.out.println(linkedList);
  1. LinkedList linkedList = new LinkedList();

    public LinkedList(){}
    
  2. 这时linkeList 的属性 first = null last = null

  3. 执行添加

    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);
            last = newNode;
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;//集合修改次数
    }
    
  4. 执行删除

    //执行removeFirst
    public E remove() {
    	return removeFirst(;
    }
    //removeFirst
    public E removeFirst() {
    	final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }
    //unlinkFirst
    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;
    }
    

5. Set

1. 基本介绍

  • 无序(添加和取出的顺序不一致),没有索引
  • 注意:去除顺序和添加顺序虽然不一致,但是==set集合的去除顺序是固定的==
  • 不允许重复元素,所以最多包含一个null
  • JDK API中Set接口的实现类有

image-20221018215840127

  • 方法列举

    image-20221018215912183

  • 遍历方式

    • 迭代器
    • 增强for循环
    • 不能用索引的方式遍历

2. HashSet

基本介绍

  • HashSet 实际上是 HashMap,HashMap底层实际上是**(数组+链表+红黑树)**

    public HashSet() {
        map = new HashMap<>();
    }
    
  • 可以存放null值,但是只能有一个null。

  • HashSet 不保证元素是有序的,取决于 hash 后,再确定索引的结果。

  • 不能加入相同元素或数据

    public class TestSet {
        public static void main(String[] args) {
            //set 不能添加相同数据的理解
            Set set = new HashSet();
            set.add("lucy");
            set.add("lucy");
            //下面两个都可加入
            set.add(new Dog("Tom"));
            set.add(new Dog("Tom"));
    
            //加深一下
            set.add(new String("hsp"));
            set.add(new String("hsp"));//加入不了
            System.out.println(set);
        }
    }
    
    class Dog {
        private String name;
    
        public Dog(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    运行结果:

    [Dog{name='Tom'}, hsp, Dog{name='Tom'}, lucy]
    

扩容机制

  1. HashSet底层是HashMap
  2. 添加一个元素时,先得到hash值->会转成->索引值
  3. 找到存储数据表table,看这个索引位置是否已经存放的有元素
    • 如果没有,直接加入
    • 如果有,调用equals比较,(需要遍历链表)如果相同,就放弃添加;如果不相同,则添加到该节点所指向链表的末尾
  4. 第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 =12
    • 如果 table 数组使用到了临界值12,就会扩容到**16*2 =32**,新的临界值就是 32*0.75 = 24,依次类推
  5. 在 Java8 中**,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且 table 的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制**
  6. 当一个数组节点的链表长度达到8,但是数组的长度小于64时,链表每添加一个元素,数组 扩容 2倍,直到数组长度大于64,链表树化,不再扩容数组
  7. 数组的扩容临界值,来自于加入集合中的元素个数,不管该元素是否各自占有一个数组

源码分析

public class TestSet {
    public static void main(String[] args) {
        Set set = new HashSet();
        set.add("java");
        set.add("php");
        set.add("java");
        System.out.println(set);
    }
}
  1. 执行 无参构造器

    public HashSet() {
            map = new HashMap<>();
    }
    
  2. 执行 add()

    public boolean add(E e) { // e = "java"
            return map.put(e, PRESENT)==null;// PRESENT:private static final Object PRESENT = new Object();
    }
    
  3. 执行 put(),执行hash方法

    public V put(K key, V value) { // key = "java" value = PRESENT 共享
            return putVal(hash(key), key, value, false, true);
    }
    
  4. hash 的计算:得到 hash 值,并不是hashCode

    static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    
  5. 执行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; //定义辅助变量
        	//tab:HashMap 的一个数组,类型为 Node[] :transient Node<K,V>[] table;
        	// if语句表示如果当前table是null,或者大小=0就是第一次扩容,到16个空间。
            if ((tab = table) == null || (n = tab.length) == 0)
                // resize():将 tab 扩容成长度为16的node数组,
                // 注意:
                //newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); 当数组已用空间为16 * 0.75时扩容,而不是等数组空间用完
                n = (tab = resize()).length;
        	/*
        		1. 根据传入的key得到的 hash 去计算该 key应该存放到 table 表的哪个索引位置,并把这个位置的对象,赋给p
        		2. 判断 p 是否为null
        			(1)如果p 为null,表示还没有存放元素,就创建一个Node (key="java" , value=PRESENT)
        				就放在该位置 tab[i] = newNode(hash,key, value,null)
        			(2)
        	*/
            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 && //如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
                    ((k = p.key) == key// 并且满足准备加入的 key 和 p 指向的 Node 节点的 key 是同一个对象
                     || (key != null && key.equals(k)))) // p 指向的 Node 结点的 key 的 equals() 和准备加入的 key比较后相同就不能加入
                    e = p;
                //再判断 p 是不是一个红黑树
                //如果是一颗红黑树,就调用 putTreeVal,来进行添加
                else if (p instanceof TreeNode)
                    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                else { // 如果当前table对应的索引位置,已经是一个链表,就使用 for 循环比较
                    /*
                    	1. 依次和该链表的每一个元素比较后,都不相同
                    		注意在把元素添加到链表后,立即判断该链表是否已经达到8个结点,就调用 treeifyBin(); 对当前这个链表进行树化(转成红黑树)
                    		注意,在转成红黑树时,要进行判断,判断条件
                                if (tab == null ll (n = tab.length)< MIN_TREEIFY_CAPACITY(64))
                                	resize();
                            如果上面条件成立,先table扩容.只有上面条件不成立时,才进行转成红黑树
                    	2. 依次和该链表的每一个元素比较过程中,如果有相同情况,就直接 break
                    */
                    for (int binCount = 0; ; ++binCount) {
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                             /*
                                注意在把元素添加到链表后,立即判断该链表是否已经达到8个结点,就调用 treeifyBin(); 对当前这个链表进行树化(转成红黑树)
                                注意,在转成红黑树时,要进行判断,判断条件
                                    if (tab == null ll (n = tab.length)< MIN_TREEIFY_CAPACITY(64))
                                        resize();
                                如果上面条件成立,先table扩容.只有上面条件不成立时,才进行转成红黑树
                   			 */
                            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 (p.hash == hash && //如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
                    ((k = p.key) == key// 并且满足准备加入的 key 和 p 指向的 Node 节点的 key 是同一个对象
                     || (key != null && key.equals(k)))) // p 指向的 Node 结点的 key 的 equals() 和准备加入的 key比较后相同就不能加入
                    	e = p;
                    由于上述语句,再第三次添加时, 添加的是 java 与第一次重复,所以返回值不为空,再结合上述
                    	return map.put(e, PRESENT)==null;
                    不为空则返回失败
                */
                if (e != null) { // existing mapping for key
                    V oldValue = e.value;
                    if (!onlyIfAbsent || oldValue == null)
                        e.value = value;
                    afterNodeAccess(e);
                    return oldValue;
                }
            }
            ++modCount;
        	//如果集合元素大于 16 * 0.75 则扩容
            if (++size > threshold)
                resize();
        	//空方法,留给 HashMap 子类去实现
            afterNodeInsertion(evict);
            return null;
    }
    

3. LinkedHashSet

基本介绍

  • LinkedHashSet是 HashSet的子类

  • LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个**数组+双向链表**

  • LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。

  • LinkedHashSet 不允许添重复元素

  • 说明

    • 在LinkedHastSet中维护了一个hash表和双向链表:(LinkedHashSet有head和tail )

    • 每一个节点有 pre 和 next 属性,这样可以形成双向链表

    • 在添加一个元素时,先求hash值,在求索引,确定该元素在 hashtable 的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset一样])

      tail.next = newElement//简单指定
      newElement.pre = tail
      tail = newEelment;
      
    • 这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致

    • 添加第一次时,直接将数组table 扩容到16,存放的结点类型是 LinkedHashHap$Entry

    • 数组是 HashMap N o d e [ ] 存放的元素 / 数据是 L i n k e d H a s h M a p Node[]存放的元素/数据是 LinkedHashMap Node[]存放的元素/数据是LinkedHashMapEntry类型,HashSet则存放的是HashMap$Node

      • //继承关系在内部类中完成
        static class Entry<K,V> extends HashMap.Node<K,V> {
        	Entry<K,V> before,after;
        	Entry(int hash,K key,V value,Node<K, V> next) {
        	super(hash,key,value,next);
        	}
        }
        

4. TreeSet

  • 无参构造器创建TreeSet时,仍然是无序的

  • 使用TreeSet提供的一个构造器,可以传入一个比较器(匿名内部类)并指定排序规则

    • 构造器把传入的比较器对象,赋给了TreeSet的底层的 TreeMap的属性this.comparator
    public TreeMap(Comparator<? super K> comparator) {
    	this.comparator = comparator;
    }
    
    • 在调用treeSet.add( “tom”),在底层会执行到
    if (cpr != null) {//cpr就是我们的匿名内部类(对象)
    do {
        parent = t;
        //动态绑定到我们的匿名内部类(对象)comparecmpI=cpr.compare(key, t.key);
        if (cmp < 0)
        	t = t.left;
        else if (cmp > 0)
        	t = t.right;
        else //如果相等,即返回0,这个Key就没有加入,表示TreeSet不能加入同一个元素
        	return t.setValue(value);
        }while (t != null);
    }
    

6. Map

1. 基本介绍

  • Map中的 key 和 value 可以是任何引用类型的数据,会封装到HashMad$Node对象中
  • Map中的key不允许重复,原因和 HashSet 一样,前面分析过源码.Map 中的 value 可以重复
  • Map 的key可以为null, value也可以为null,注意 key 为 null, 只能有一个,value 为 null ,可以多个.
  • key 和 value之间存在单向一对一关系,即通过指定的key 总能找到对应的 value
  • 当有相同的 key 时,等同于替换
  • k-v最后是 HashMap$Node node = newNode(hash,key,value,null)
  • 理解 EntrySet
    • k-v为了方便程序员的遍历,还会创建EntrySet 集合,该集合存放的元素的类型 Entry,而一个Entry对象就有k, v EntrySet<Entry<K, V>>,即:transient set<Hap.Entry<K, V>> entrySet;
    • entrySet中,定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node这时因为 static class Node<K,V> implements Map.Entry<K, V>

2. 常用方法

image-20221024153838532

3. 遍历方法

/*
	containsKey:查找键是否存在
	keySet:获取所有的键
	entrySet:获取所有关系
	k-vvalues:获取所有的值
*/
Map<String,Integer> map = new HashMap<>();
map.put("101",1);
map.put("102",2);
map.put("103",3);
map.put("104",4);
map.put(null,1);
map.put("106",1);

//第一种:keySet(简洁)
Set<String> sets = map.keySet();
for(String key : sets){
    System.out.println(key + "-" + map.get(key));
}

//第二种:EntrySet
Set entries = map.entrySet();
for(Object entry : entries){
    //将 entries 转换为 EntrySet
    Map.Entry m = (Map.Entry)entry;
    System.out.println(m.getKey() + "-" + m.getValue());
}

4. HashMap(线程不安全)

  • (k,v)是一个HashMap$Node实现了Map.Entry<K,V>
  • jdk7.0的hashmap底层实现==[数组+链表],jdk8.0底层[数组+链表+红黑树]==

扩容机制(与HashSet完全一样)

  • HashMap 底层维护了 Node 类型的数组 table,默认为 null
  • 当创建对象时,将加载因子(loadfactor)初始化为0.75.
  • 当添加 key-val 时,通过 key 的哈希值得到在 table 的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的 key 是否和准备加入的 key 相等,如果相等,则直接替换 val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
    • 第1次添加,则需要扩容 table 容量为16,临界值(threshold)为**12**.
    • 以后再扩容,则需要扩容 table 容量为原来的2倍,临界值为原来的2倍,即 24,依次类推。在 Java8 中,如果一条链表的元素个数超过 TREEIFY_THRESHOLD(默认是8),并且table的大小>= MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

5. HashTable(线程安全)

基本介绍

  • 存放的元素是键值对:即 K-V
  • hashtable的键和值都不能为null,否则会抛出NullPointerException,HashTable使用方法基本上和HashMap一样
  • hashTable是线程安全的,hashMap是线程不安全的
  • 底层有数组:Hashtable$Entry[] 初始化大小为11
  • 临界值threshold 8 =11 *0.75

扩容机制

  • 当if (count >= threshold)满足时,就进行扩容,按照int newCapacity = (oldCapacity <<1) +1;的大小扩容.
  • 大于等于临界值时,将数组扩到原来的两倍加一

Properties

  • Properties 类**继承自 Hashtable 类并且实现了Map 接口**,也是使用一种键值对的形式来保存数据。
  • 它的使用特点和 Hashtable 类似
    • 键和值都不能为null
  • Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
    • 说明:工作后xoxx.properties文件通常作为配置文件

6. TreeMap

7. Collections工具类

  • Collections是一个操作Set、List和 Map等集合的工具类
  • Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
  • 方法
    • reverse(List):反转List中元素的顺序
    • shuffle(List):对List集合元素进行随机排序
    • sort(List):根据元素的自然顺序对指定List集合元素按升序排序
    • sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
    • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    • Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
    • Object min(Collection)
    • Object min(Collection,Comparator)
    • int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    • void copy(List dest,List src):将src中的内容复制到dest中
    • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值