初学Java之集合篇

集合

1、什么是集合

  • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
  • 和数组区别:
    • (1)数组长度固定,集合长度不固定
    • (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置:java.util.*;

2、Collection体系集合

在这里插入图片描述

2.1 Collection父接口

  • 特点:代表一组任意类型的对象,无序,无下标,不能重复。

  • 方法:

    • boolean add(Object obj) //添加一个对象

    • boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中。

    • void clear() //清空此集合中的所有对象

    • boolean contains(Object o ) //检查此集合中是否包含o对象

    • Boolean equals(Object o)//比较此集合是否与指定对象相等

    • boolean isEmpty()//判断此集合是否为空

    • boolean remove(Object o)//在此集合中移除o对象

    • int size()//返回此集合中的元素个数。

    • Object[] toArray()//将此集合转换成数组

2.1.1 List子接口
  • 特点:有序、有下标、元素可以重复

  • 方法:

    • void add(int index, Object o) //在index 位置插入对象o
    • boolean addAll(int index,Collection c) //将一个集合中的元素添加到此集合中的index位置
    • Object get(int index) //返回集合中指定位置的元素
    • Object get(int index) //返回集合中指定位置的元素
    • List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素
2.1.2 List实现类
  • ArrayList**[重点]**:
  1. 数组结构实现,查询快、增删慢;

  2. JDK1.2版本,运行效率快、线程不安全。

  3. 源码分析:

    1. ArrayList()构造方法
    private static final int DEFAULT_CAPACITY = 10;
    //默认容量是10
    
    public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    //注意:如果没有向集合中添加任何元素时,默认容量是0;添加一个元素之后,容量变成10; 超过10之后,每次扩容大小是原来的1.5倍。
    
    
    transient Object[] elementData; // non-private to simplify nested class access
    //存放元素的数组elementData
    
    private int size;
    //实际元素个数
    
    
    

    2.add方法

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!   扩容
    elementData[size++] = e;
    return true;
}


 private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);// DEFAULT_CAPACITY 为10
        }
        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);  //10+(10\2),右移一位是除于2,等于每次扩容大小是原来的1.5倍
        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(被替代掉的):
  1. 数组结构实现,查询快、增删慢;

  2. JDK1.0版本,运行效率慢、线程安全。

  • LinkedList:
    1. 链表结构实现,增删快,查询慢。
    2. 源码分析
transient int size = 0; //集合的大小

transient Node<E> first;//链表的头节点

transient Node<E> last;//链表的尾节点


   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++;
    }


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


  • ArrayList与LinkedList不同结构实现方式
    在这里插入图片描述
2.1.3 Set子接口以及Set实现类
  • 特点:无序、无下标、元素不可重复

  • 方法:全部继承来自Collection的方法。

  • HashSet[重点]

    1. 基于HashCode实现元素不重复
    2. 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
  • TreeSet:

    1. 基于排列顺序实现元素不重复。
    2. 实现了SortedSet接口,对集合元素自动排序。
    3. 元素对象的类型必须实现Comparable接口,指定排序规则。
    4. 通过CompareTo方法确定是否为重复元素
  • LinkHashSet

2.2 Collection 工具类

  • 概念:集合工具类,定义了除了存取以外的集合常用方法
  • 方法:
    1. public static void reverse(List<?> list) //反转集合中元素的顺序
    2. public static void shuffle(List<?> list) //随机重置集合元素的顺序
    3. public static void sort(List list) //升序排序(元素类型必须实现Comparable接口)

3、泛型

  • Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。

  • 常见形式有泛型类、泛型接口、泛型方法。

  • 语法:

    <T,…> T 称为类型占位符,表示一种引用类型

  • 好处

    1. 提高代码的重用性
    2. 防止类型转换异常,提高代码的安全性

4、泛型集合

  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。

  • 特点:

    • 编译时即可检查,而非运行时抛出异常
    • 访问时,不必类型转换(拆箱)。
    • 不同泛型之间引用不能相互赋值,泛型不存在多态。

5、Map体系集合

在这里插入图片描述

5.1 Map接口的特点

  1. 用于存储任意键值对(Key-Value)
  2. 键:无序、无下标、不允许重复(唯一)
  3. 值:无序、无下标、允许重复

5.2 Map父接口

  • 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复
  • 方法:
    1. V put(K key, V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
    2. Object get(Object key) //根据键获取对应的值。
    3. Set //返回所有key
    4. Collection values() //返回包含所有值的Collection集合。
    5. Set<Map.Entry<K,V>> //键值匹配的set集合

在这里插入图片描述

5.3 Map的实现类

5.3.1 HashMap [重点]
  • JDK1.2版本,线程不安全,运行效率快;允许用null 作为key或是value。
  • 源码分析:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 //hashMap初始容量大小

static final int MAXIMUM_CAPACITY = 1 << 30; //hashMap的数组最大容量

static final float DEFAULT_LOAD_FACTOR = 0.75f;// 默认加载因子
    
static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当链表长度大于8时,调整成红黑树

static final int UNTREEIFY_THRESHOLD = 6; //jdk1.8 当链表长度小于6时,调整成链表

static final int MIN_TREEIFY_CAPACITY = 64;// jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树

transient Node<K,V>[]  table;// 哈希表中的数组

size; //元素个数



2.无参构造:

public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

3.put方法

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

4.putVal方法

/**
 * Implements Map.put and related methods.
 *
 * @param hash hash for key
 * @param key the key
 * @param value the value to put
 * @param onlyIfAbsent if true, don't change existing value
 * @param evict if false, the table is in creation mode.
 * @return previous value, or null if none
 */
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;
}
  • 总结:
  1. HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table的容量调整为16
  2. 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。
  3. jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
  4. jdk1.8 当链表长度小于6时,会调整成链表
  5. jdk1.8 以前,链表时头插入,jdk1.8以后时是尾插入
5.3.2 Hashtable
  • JDK1.0 版本,线程安全,运行效率慢;不允许null作为key或是value.
5.3.3 Properties
  • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
5.3.4 TreeMap
  • 实现了SortedMap接口(是Map的子接口),可以对key自动排序。

6 Properties

  • Properties:属性集合
  • 特点
    1. 存储属性名和属性值
    2. 属性名和属性值都是字符串类型
    3. 没有泛型
    4. 和流有关
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值