常用集合类

Posted Al_tair

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用集合类相关的知识,希望对你有一定的参考价值。

常用集合类

大家好呀!我是小笙!我学习了韩顺平老师的类和对象的知识,收获颇丰!现在来和大家分享笔记!

集合类

集合框架体系

Collection接口框架

补充框架图

Map接口框架

补充框架图

Collection接口

Collection 实现 Iterable接口 : public interface Collection extends Iterable

遍历方式

遍历方式-迭代器

Iterator接口 又称为 迭代器,主要用于遍历Collcection集合中的元素

所有实现了Collection接口的集合类都有一个Iterator()方法,用来返回一个迭代器

迭代器方法

变量和类型方法描述
default voidforEachRemaining(Consumer<? super E> action)对每个剩余元素执行给定操作,直到处理完所有元素或操作引发异常。
booleanhasNext()如果迭代具有更多元素,则返回 true
Enext()返回迭代中的下一个元素。
default voidremove()从底层集合中移除此迭代器返回的最后一个元素(可选操作)。
// Iterator方法的使用实例
public class Iterator01 
    public static void main(String[] args) 
        List list = new ArrayList();
        list.add(new Book("三国演义",10));
        list.add(new Book("水浒传",20));
        list.add(new Book("西游记",15));

        Iterator iterator = list.iterator();
        while(iterator.hasNext())
            System.out.println(iterator.next());
        
        // 退出循环之后,迭代器指向最后一个元素
        // iterator.next(); // 抛出异常 NoSuchElementException
        // 需要重置迭代器  iterator = list.iterator();
    
    static class Book
        private String name;
        private int price;

        public Book(String name, int price) 
            this.name = name;
            this.price = price;
        

        @Override
        public String toString() 
            return "Book" +
                "name='" + name + '\\'' +
                ", price=" + price +
                '';
        
    

遍历方式-for增强

特点:只能用于遍历集合和数组(简化版迭代器)

基本语法:

 for(元素类型 元素名:集合名或数组名) 
     // 访问元素
 

实例

public class ForS 
    public static void main(String[] args) 
        List list = new ArrayList();
        list.add(new Toy("猛虎王",10));
        list.add(new Toy("霹雳火",20));
        list.add(new Toy("洛洛",15));

        // 增强for 本质仍然是迭代器
        // 集合
        for (Object b:list) 
            System.out.println(b.toString());
        
        // 数组
        int[] num = 2,4,5,6;
        for (int n:num
             ) 
            System.out.println(n+"  ");
        
    
    static class Toy
        private String name;
        private int price;

        public Toy(String name, int price) 
            this.name = name;
            this.price = price;
        
        @Override
        public String toString() 
            return "Toy" +
                    "name='" + name + '\\'' +
                    ", price=" + price +
                    '';
        
    

// debug 跳转 底层也是迭代器
// 跳转1
public Iterator<E> iterator() 
    return new Itr();

// 跳转2
public boolean hasNext() 
    return cursor != size;

// 跳转3
public E next() ......等等
遍历方式-普通for循环
public static void main(String[] args) 
    List list = new ArrayList();
    list.add("张三丰");
    list.add("秦天柱");
    for (int i = 0; i < list.size(); i++) 
        System.out.println(list.get(i));
    

Collection接口特征

  1. 可以实现存放多个元素,每个元素可以是Object类
  2. 没有直接实现的子类,都是通过它的子接口Set和List来实现的

Collection的常用方法

List list = new ArrayList();
// add 添加单个元素
list.add("lns");
list.add(520); // 自动装箱 new Integer(520)
list.add("zlr");
System.out.println(list.toString()); // [lns, 520, zlr]
/*
*  父类AbstractCollection: toString方法
*  public String toString() 
*    Iterator<E> it = iterator(); // 创建迭代器进行遍历该集合
*    if (! it.hasNext())
*        return "[]";
*
*    StringBuilder sb = new StringBuilder();
*    sb.append('[');
*    for (;;) 
*        E e = it.next();
*        sb.append(e == this ? "(this Collection)" : e);
*        if (! it.hasNext())
*            return sb.append(']').toString();
*         sb.append(',').append(' ');
*    
*  
*/

// remove 删除指定元素
list.remove(1); // 等价于 list.remove(520);
System.out.println(list); // [lns, zlr]

// contains 查找元素是否存在
System.out.println(list.contains("lns")); // true

// size 获取元素个数
System.out.println(list.size()); // 2

// isEmpty 判读是否为空
System.out.println(list.isEmpty()); // false

// clear 清空
list.clear();
System.out.println(list); // []

// addAll 添加多个元素
List list2 = new ArrayList();
list2.add("lns");
list2.add("love");
list2.add("zlr");
list.addAll(list2);
System.out.println(list); // [lns, love, zlr]

// containsAll 查找多个元素是否存在
System.out.println(list.containsAll(list2)); // true

// removeAll 删除多个元素
list.add("!");
list.removeAll(list2);
System.out.println(list); // [!]

List接口

Collection接口的子接口 (队列数据结构)

特点

  • List集合类元素顺序有序,且可以重复
  • List集合类中的每个元素都有其对应的顺序索引
// List集合类元素顺序有序,且可以重复
List list = new ArrayList();
list.add("das");
list.add("tom");
list.add("tom");
System.out.println(list); // [das, tom, tom]
// List集合类中的每个元素都有其对应的顺序索引
System.out.println(list.get(0));  // das
List常用方法
public class ListMethod 
    public static void main(String[] args) 
        List list = new ArrayList();
        list.add("张三丰");
        list.add("秦天柱");
        // add 插入一个对象
        list.add(1,"lns");
        System.out.println(list); // [张三丰, lns, 秦天柱]

        List list2 = new ArrayList();
        list2.add("风火轮");
        list2.add("大黄蜂");
        // addAll 插入所有元素
        list.addAll(1,list2);
        System.out.println(list); // [张三丰, 风火轮, 大黄蜂, lns, 秦天柱]

        // indexOf 返回该对象首次出现的索引位置
        System.out.println(list.indexOf("lns")); // 3

        // lastIndexOf 返回该对象最后一次出现的索引位置
        list.add(1,"张三丰");
        System.out.println(list ); // [张三丰, 张三丰, 风火轮, 大黄蜂, lns, 秦天柱]
        System.out.println(list.lastIndexOf("张三丰")); // 1

        // set 替换对象数据
        list.set(1,"妞妞");
        System.out.println(list); // [张三丰, 妞妞, 风火轮, 大黄蜂, lns, 秦天柱]

        // subList 返回范围为[fromIndex,toIndex)位置的子集合 该方法返回的是子串集合的地址索引
        list = list.subList(0, 3);
        System.out.println(list); // [张三丰, 妞妞, 风火轮]

    

ArrayList类

是由数组实现数据存储

特点:

  • 元素可以是null,并且可以有多个

  • ArrayList是线程不安全的,不能在多线程的情况下使用

    // 对比这两种源码 区别在于是否线程安全  synchronized
    // ArrayList源码
    public boolean add(E e) 
        modCount++;
        add(e, elementData, size);
        return true;
    
    // Vector源码
    public synchronized boolean add(E e) 
        modCount++;
        add(e, elementData, elementCount);
        return true;
    
    
ArrayList源码分析

  1. ArrayList类数据存储在Object类数组中(elementData)

    transient Object[] elementData; // transient 表示该属性不会被序列化
    
  2. 当使用无参构造方法创建该对象,初始elementData容量为0,第一次添加数据,扩容到10容量,以后每次扩容,则会扩大当前容量的1.5倍

  3. 如果使用指定大小的有参构造器,则初始elementData容量为指定大小,如果需要扩容,也是直接扩容1.5倍

扩容机制

无参构造器

1.设置断点

2.debug跳转

// 跳转1
public boolean add(E e) 
    modCount++; // 记录集合被修改的次数  如果madCount的值因为线程原因意外改变,则抛出异常
    add(e, elementData, size); // e:传入的数据 elementDate:Object数组 size:数组元素数量
    return true;

// 跳转2
private void add(E e, Object[] elementData, int s) 
    if (s == elementData.length) // s:数组元素数量 elementDate.length:数组容量 
        elementData = grow(); // 只有当容量够用,不会调用该方法
    elementData[s] = e; // 数组添加数据
    size = s + 1; 

// 跳转3
private Object[] grow() 
    return grow(size + 1); 

// 跳转4
private Object[] grow(int minCapacity)  // minCapacity:当前元素个数+1
    int oldCapacity = elementData.length; // 记录原容量
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) //判断容量是否为0
        //  传入newLength方法的参数:原容量,超出容量,0.5倍容量大小
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                  minCapacity - oldCapacity, oldCapacity >> 1 ); // >> 1 相当于乘0.5
        return elementData = Arrays.copyOf(elementData, newCapacity); // 扩容,保留原数据
     else 
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
      // DEFAULT_CAPACITY 10   如果是容量为0,第一次扩容默认为10

// 当传入第11个数据时候跳转5
public static int newLength(int oldLength, int minGrowth, int prefGrowth) 
    // assert oldLength >= 0
    // assert minGrowth > 0

    int newLength = Math.max( minGrowth,prefGrowth ) + oldLength; // 当超出容量,则扩容1.5倍
    if (newLength - MAX_ARRAY_LENGTH <= 0) 
        return newLength;
    
    return hugeLength(oldLength, minGrowth);

有参构造器

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

Vector类

是由数组实现数据存储

Vector的基本介绍

// Vector的类定义
public class Vector<E>extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
// Vector底层本质也是对象数组
protected Object[] elementData;

// Vector是线程安全
// 通常方法被 synchronized 关键字修饰

Vector源码分析

/*
 * The amount by which the capacity of the vector is automatically
 * incremented when its size becomes greater than its capacity.  If
 * the capacity increment is less than or equal to zero, the capacity
 * of the vector is doubled each time it needs to grow.
 * 当向量的大小变得大于其容量时,向量的容量自动增加的量。如果容量增量小于或等于零,
 * 则每次需要增长时,向量的容量都会增加一倍
 * @serial
 */
protected int capacityIncrement;

private Object[] grow(int minCapacity) 
    int oldCapacity = elementData.length;
    int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, 							capacityIncrement > 0 ? capacityIncrement : oldCapacity);
    return elementData = Arrays.copyOf(elementData, newCapacity);


public static int newLength(int oldLength, int minGrowth, int prefGrowth) 
    // assert oldLength >= 0
    // assert minGrowth > 0

    int newLength = Math.max(minGrowth, prefGrowth) + oldLength; // 2倍
    if (newLength - MAX_ARRAY_LENGTH <= 0) 
        return newLength;
    
    return hugeLength(oldLength, minGrowth);


Vector和ArrayList的比较

底层结构版本线程安全扩容机制
ArrayList可变数组jdk1.2不安全,但效率高如果有参构造 扩容1.5倍;如果是无参1.第一次默认10,第二次扩容1.5倍
Vector可变数组jdk1.0安全,但效率不高如果有参构造 扩容2倍;如果是无参1.第一次默认10,第二次扩容2倍
LinkedList类

LinkedList类基本介绍

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

LinkedList类的底层结构

  1. 该类底层是一个双向链表

  2. 其中含有两个属性:first 和 last 分别指向首节点和尾节点

  3. 每个节点里面含有prev,next,item三个属性,其中通过prev指向前一个节点,通过next指向后一个节点,用item来存储数据

  4. 进行添加和删除操作,效率比数组高

添加数据源码分析

// 添加第一个数据
// 跳转1
public boolean add(E e)  // 增加数据
    linkLast(e);
    return true;

// 跳转2
void linkLast(E e) 
    final Node<E> l = last; // last:null 第一次添加last为null
    final Node<E> newNode = new Node<>(l, e, null); //l:null e:"lns"  说明prev和next指向null
    last = newNode; // last 指向尾节点 
    if (l == null) // 添加第一个节点
        first = newNode; //  first和last都指向同一个节点
    else
        l.next = newNode; 
    size以上是关于常用集合类的主要内容,如果未能解决你的问题,请参考以下文章

Nvidia 擎天柱 NvOptimusEnablement

Java五个最常用的集合类之间的区别和联系

在 LG 擎天柱上使用 RingtoneManager.getRingtone

常用集合类

一周AI新鲜事“擎天柱”霸气登场/全球创新指数中国排名11位/摩尔定律死了,又活了?...

一周AI新鲜事“擎天柱”霸气登场/全球创新指数中国排名11位/摩尔定律死了,又活了?...