[笔记] Java基础(7)-集合

139 阅读6分钟

1. 集合体系

  • 集合:长度可变的容器,元素只能存放任意引用数据类型,基本数据类型需转为包装类
  • Collection:单列
    • List:有序
      • ArrayList:数组,线程不安全
      • LinkedList:链表,线程不安全
      • Vector:数组,线程安全
    • Set:无序
      • HashSet:哈希表
        • LinkedHashSet:链表
      • TreeSet:二叉树,自动排序
  • Map:双列
    • HashMap:无序,线程不安全,键值可以为null
      • LinkedHashMap:有序
    • Hashtable:线程安全,键值不能为null
    • TreeMap:二叉树,自动排序

2. ArrayList类

  • ArrayList类:java.util.ArrayList
  • boolean add(E e):添加元素,永远返回true;Set集合元素重复是返回false
  • boolean remove(Object o):移除第一次出现的元素,成功返回true;该方法传入int时不会自动装箱
  • void clear():清空集合
  • bolean contains(Object o):判断是否包含元素
  • boolean isEmpty():判断是否为空
  • int size():获取元素个数
  • Object[] toArray():将集合转为数组
  • boolean addAll(Collection<? extends E> c):添加c中所有元素;如果使用add()方法则会将c当作一个对象
  • boolean removeAll(Colection<? extends E> c):移除c中所有元素
  • boolean containsAll(Collection<? extends E> c):判断是否饱和c中所有元素
  • boolean retainAll(Collection<? extends E> c):取交集存入原集合中,原集合有变化是返回true,无变化是返回false
  • Iterator<E> iterator():获取迭代器
    • boolean hasNext():判断是否还有元素
    • E next():获取下一个元素
    • void remove():移除返回的最后一个元素
  • void add(int index, E element):添加到指定位置,索引不能大于集合长度
  • E remove(int index):删除指定位置的元素,返回被删除的元素
  • E get(int index):获取指定位置的元素
  • E set(int index, E element):设置指定位置的元素,返回被替换的元素
  • ListIterator<E> listIterator():获取列表迭代器;List特有的方法
  • 并发修改异常ConcurrentModeficationException:遍历时添加元素时会产生
    • 解决方法:通过ListIterator添加元素
  • VectorArrayList都是由数组实现;Vector线程安全,效率低
  • ArrayListLinkedList都是线程不安全的,LinkedList由链表实现
  • ArrayList中的contains()remove()方法底层依赖对象的equals方法,没重写之前继承于Objectequals()方法

3. ListIterator接口

  • ListIterator接口:java.util.ListIterator
  • 可以通过List获取该迭代器
  • void add(E e):添加元素
  • boolean hasNext():判断是否有下一个元素
  • boolean hasPrevious():判断是否有上一个元素
  • E next():获取下一个元素
  • E previous():获取上一个元素
  • int nextIndex():获取下一个元素的索引
  • int previousIndex():获取上一个元素的索引
  • void remove():移除next()previous()返回的最后一个元素
  • void set(E e):使用e替换next()previous()返回的最后一个元素

4. LinkedList类

  • LinkedList类:java.util.LinkedList
  • LinkedList类的方法大部分与ArrayList类似,存在部分特有方法
  • void addFirst(E e):添加元素到头部
  • void addLast(E e):添加元素到尾部
  • E getFirst():获取第一个元素
  • E getLast():获取最后一个元素
  • E removeFirst():移除第一个元素
  • E removeLast():移除最后一个元素
  • E get(int index):获取指定索引的元素

5. HashSet类

  • HashSet特点:无序,元素不可重复,无索引;ArrayList有索引
  • boolean add(E e):添加重复元素时返回false
  • 保证元素唯一:底层调用对象的hashcode()equals()方法;当hashcode()值一致时,调用equals()方法比较,为false时存入
  • hashcode()方法使用31的原因:31为质数;31方便计算(32-1);31不大不小
  • LinkedHashSet类:继承与HashSet;元素有序(按存入顺序);元素唯一;无索引

6. TreeSet类

  • TreeSet类:元素唯一,存入时会进行排序
  • 排序依赖Comparable<T>接口的compareTo()方法,故对象需要实现该接口;即将存入的元素会调用compareTo()方法
    • int compareTo(T t):返回0表示相等(相等时不存入),返回负数表示比t小,返回正数表示比t大;t表示已存入元素
  • TreeSet结构为二叉树,小的元素在左边,大的元素在右边
  • TreeSet的构造方法可传入比较器
    • 示例:new TreeSet<>(new Comparator() {});
    • Comparator接口有compare()equals()方法
    • ArrayList中的sort方法也可以使用Comparator
  • TreeSet排序方式:自然排序(Comparable)与比较器排序(Comparator
    • 构造函数如果传入Comparator,优先按比较器(compare()方法)排序,否则按自然排序(compareTo()方法)
    • 自然排序会先将类型提升为Comparable

7. Map接口

  • Map:双列集合,key是唯一的,重复向键里存值会将之前的值替换掉
  • 先有双列集合,单列集合如HashSet底层依赖HashMap
  • V put(K key, V value):添加键值对,键存在时返回被替换的值,没有返回null
  • void clear():清除所有元素
  • V remove(Object key):移除key对应的元素,返回被移除的元素
  • boolean containsKey(Object key):判断是否包含key
  • boolean containsValue(Object value):判断是否包含value
  • boolean isEmpty():判断集合是否为空
  • V get(Object key):根据key获取value
  • Set<Map.Entry<K,V>> entrySet():获取键值对组成的集合
  • Set<K> keySet():获取所有key的集合
  • Collection<V> values():获取所有value的集合
  • int size():获取集合的大小
  • 双列集合没有迭代器,要迭代需要先获得keyentry组成的单列集合
    • 示例1:for(K key : map.keySet()) { ... }
    • 示例2:for(Map.Entry<K,V> entry : map.entrySet()) { ... }
    • Map.Entry<K,V>Map接口里的内部接口,代表键值对对象
      • K getKey():获取键
      • V getValue():获取值
      • V setValue(V value):用指定值替换当前entry对象的value
  • LinkedHashMap类:继承于HashMap类;HashMap是无序的,LinkedHashMap是有序的
  • TreeMap类:元素唯一,存入时自动排序;排序原理与TreeSet类似,也有自然排序与比较器排序
  • Hashtable类:HashtableHashMap都是双列集合,都采用哈希算法
    • 区别
      • Hashtable是线程安全的,效率低;HashMap是线程不安全的,效率高
      • HashMap可以存null键和null值;Hashtable不能存null键和null
      • HashMapJDK1.2之后加入;HashtableJDK1.0加入

8. Collections类

  • Collections类:java.util.Collections
  • 该类方法都是静态方法,用于处理集合
  • static<T> void sort(List<T> list):对List集合进行排序,底层调用compareTo()方法
  • static<T> int binarySearch(List<T> list, T key):二分查找
  • static void reverse(List<?> list):反转
  • static<T> T max(Collection<?> c):获取最大值
  • static void shuffle(List<?> list):随机置换元素顺序

9. 泛型

  • 泛型Generic:提高安全性,将程序运行错误转换到编译期,对象不用强制类型转换;前后泛型需要一致,JDK1.7可以省略(菱形泛型)

  • 自定义泛型

    class Name<Q> {
        private Q q;
        public Q getQ() {
            return this.q;
        }
        public void setQ(Q q) {
            this.q = q;
        }
        /* 方法泛型与类泛型不一致时需要单独声明 */
        public<T> void fun1(T t) { ... }
        /* 静态方法的泛型不能与类的泛型一致,需要单独声明 */
        public static<W> void fun2(W w) { ... }
    }
    
  • 泛型接口与实现类

    /* 定义泛型接口 */
    interface Inter<T> {
        public void fun(T t);
    }
    /* 定义实现类,无泛型方式 */
    class Name implements Inter<String> {
        public void fun(String t) { ... }
    }
    /* 定义实现类,有泛型方式 */
    class Name<T> implements Inter<T> {
        public void fun(T t) { ... }
    }
    
  • 泛型通配符

    • <?>:表示任意类型,当右边的泛型不确定是使用
    • <? extends E>:向下限定,E及其子类
    • <? super E>:向上限定,E及其父类

10. 增强for循环

  • 增强for循环:Collection底层由迭代器实现;数组底层由普通for循环实现

  • 普通for循环删除元素是,索引需要向前移动

  • 迭代器循环时,移除元素需要使用迭代器自身的remove()方法

    for (Iterator<String> it = list.iterator(); it.hasNext();) {
        if (it.next() == 1) {
            it.remove();
        }
    }
    
  • 增强for循环不能删除集合元素,会出现并发修改异常,故只能对集合进行遍历

11. 数组与集合相互转换

  • 数组转集合
    • 方法:static List<T> Arrays.asList(T... a)
    • 该方法产生的集合调用add()remove()方法时会产生异常
    • 基本数据类型的数组使用该方法时,会将整个数组当作一个对象,等价于:List<int[]> list = Arrays.asList(new int[]{1, 2, 3})
  • 集合转数组
    • 方法:T[] toArray(T[] a)
    • 示例:String[] arr = list.toArray(new String[0])
    • 当数组长度小于集合size时,转换的数组长度与size相等
    • 当数组长度大于集合size时,转换的数组长度与指定的长度一样