【Java基础】06-Java集合框架

Java 集合框架

Java 的集合框架将一些常用的数据结构封装成类,相当于 C++ STL 库中实现的抽象数据类型。其中声明了对各种集合类型执行的一般操作。如下定义了实现这些抽象数据类型的接口及它们的继承关系,包括 Set, List, Queue, Map, SortedSet, SortedMap 等,继承关系如下。
【Java基础】06-Java集合框架_第1张图片
Collection 是 Java 定义的一个接口,实现该接口的是一个抽象类 AbstractCollection,通过继承关系,其子类陆续实现了一些抽象数据结构,如下所示。
【Java基础】06-Java集合框架_第2张图片
Collection 接口中定义了一些常用方法,包括:

  • int size() —— 返回集合对象中包含的元素个数
  • boolean isEmpty() —— 判断集合对象中是否还包含元素,如果没有任何元素,则返回 true
  • boolean contains (Object obj) —— 判断对象是否在集合里面
  • boolean containsAll (Collection c) —— 判断方法的接受者对象是否包含集合中的所有元素
  • boolean add (Object obj) —— 向集合中增加对象
  • boolean addAll (Collection c) —— 将参数集合中的所有元素增加到接收者集合中
  • boolean remove (Object obj) —— 从集合中删除对象
  • boolean removeAll (Collection c) —— 将参数集合中的所有元素从接收者集合中删除
  • boolean retainAll (Collection c) —— 在接收者集合中保留参数集合中的所有元素,其它的元素都删除。
  • void clear() —— 删除集合中的所有元素。

Set 接口

Set 为集合接口,其中的 equals() 方法重写了 Object 类中的 equals() 方法。Object 类中的 equals() 方法是当比较的对象是同一个时,而不是内容相同才返回 true。而 Set 类中的 equals() 方法是判断两个对象的内容是否相同。

实现 Set 接口的类

基础的类包括 Hashset, TreeSet
其它实现的类和其子类:

  • AbstractSet
  • ConcurrentSkipListSet (基于跳表)
  • CopyOnWriteArraySet
  • EnumSet
  • JobStateReasons
  • LinkedHashset

SortedSet 接口

SortedSet 接口中的元素是升序排列的(C++ 中的 set 类本身是排好序的,相当于实现了这里的 SortedSet 接口),而且增加了和次序有关的操作,常用语存放词汇表这样的内容。实现它的类包括:ConcurrentSkipListSet, TreeSet。

List 接口

List 接口中可包含重复的元素,而且每个元素是有顺序的,每个元素都有一个 index 值(从 0 开始)标明元素在列表中的位置。

实现 List 接口的类

  • Vector:动态数组,线程安全,但是现在不太使用了(随机访问较为慢)
  • ArrayList:相当于实现数组的类,但是是动态数组,随机访问速度极快,非线程安全
  • LinkedList:内部实现是链表,适合于需要频繁插入和删除操作的应用场景
  • Stack:后进先出
  • 其它:AbstractList, AbstractSequentialList, AttributeList, CopyOnWriteArrayList, RoleList, RoleUnresolvedList

Queue 接口

先进先出(FIFO)

实现 Queue 接口的类

  • LinkedList:先进先出的 List,链表实现
  • PriorityQueue:优先队列,实现了堆
  • 其它:AbstractQueue, ArrayBlockingQueue, ArrayDeque(双端队列), ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue

Map 接口

Map 用于维护键值对 (Key - Value),其中键的值不能重复,键和值的类型可以不同,所以泛型的传入类型有连个,分别为 Key 和 Value。

以下是 Map 接口和它的子接口和实现:
【Java基础】06-Java集合框架_第3张图片

实现 Map 接口的类

  • HashMap
  • TreeMap
  • 其它:AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap(基于跳表), EnumMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupprot, UIDefaults, WeakHashMap

SortedMap 接口

是 Map 的子接口,其中的关键字是升序排列的(C++ 中的 map 类实现时其实就将关键字排序了)。

实现的接口

  • TreeMap
  • ConcurrentSkipListMap(支持并发)

算法

大多用于 List 对象,对标 C++ STL 中的 algorithm。其中的 min() 和 max() 适用于任何的实现了 Collection 接口的对象。

sort

和 C++ 中的 sort 差不多

  • 默认将 List 元素按照升序排列
  • 简单形式下将基本数据类型的元素按照自然次序排列,或者是元素的类实现了 Comparable 接口
  • 第二种形式是附加一个 Comparator 对象作为参数,可以自己规定比较的规则, 可以用于实现反序或者特殊次序的排序。
  • 复杂度为 nlog(n),稳定。

shuffle

用于将 List 中的元素打乱,采用随机的方式打乱。

其它常用算法

  • reverse():将一个 List 中的元素反向排列
  • fill():将某个值覆盖 List 中的每一个元素, 常常用于 List 的初始化
  • copy():接受源 List 和目标 List,将源中的元素复制到目标,覆写其中的内容,目标 List 的长度必须不得小于原 List,如果目标 List 更长,多余部分的内容保留原样。

二分查找,binarySearch()

  • 在一个有序的 List 中查找指定的元素,List 中的元素必须已经排好序了。
  • 和 sort() 一样,可以按照自然升序规则查找,也可以传入一个 Comparator 对象,自行设定比较规则,并假定 List 就是按照这种规则排序的。
  • 容器必须是实现了 RandomAccess 接口的,否则只能线性查找。

min() 和 max()

可以用于任何集合对象,min() 返回最小值,max() 返回最大值。同样默认按照自然顺序规则计算返回,也可以自己定义 Comparator 对象自己定义比较规则。

数组的实用方法

Arrays 类

  • 在 java.util.Arrays 包中
  • 常用方法
  1. fill (type[] a, type val):将 a 的所有数据填充为 val。
  2. equals (type[] a, type[] b):比较是否内容相等,而不是比较是否同一。
  3. sort (type[] a):排序,如前文介绍
  4. binarySearch ():二分查找
  5. asList (T… a):将数组转化为 ArrayList 类型
  6. toString (数组的引用):实现到 String 的转换

测试数组的复制和填充

import java.util.Arrays;

public static void copyArrays(){
    int[] a = new int[6];
    int[] b = new int[10];
    Arrays.fill(a, 47);
    Arrays.fill(b, 99);
    for(int i: a){
        System.out.print(i+"\t");
    }
    System.out.println();
    for(int i: b){
        System.out.print(i+"\t");
    }
    System.out.println();
    System.arraycopy(a, 0, b, 0, a.length);
    for(int i: b){
        System.out.print(i+"\t");
    }
    System.out.println();
    int[] c = new int[5];
    Arrays.fill(c, 103);
    System.arraycopy(c, 0, a, 0, c.length);
    for(int i: a){
        System.out.print(i+"\t");
    }
    System.out.println();
    Integer[] u = new Integer[5];
    Integer[] v = new Integer[14];
    Arrays.fill(u, new Integer(34));
    Arrays.fill(v, new Integer(50));
    System.arraycopy(u, 0, v, 5, u.length);
    for(Integer i: v){
        System.out.print(i+"\t");
    }
    System.out.println();
}

测试的结果如下:

47 47 47 47 47 47
99 99 99 99 99 99 99 99 99 99
47 47 47 47 47 47 99 99 99 99
103 103 103 103 103 47
50 50 50 50 50 34 34 34 34 34 50 50 50 50

测试数组的比较

import java.util.Arrays;

public static void compareArrays(){
    int[] a1 = new int[10];
    int[] a2 = new int[10];
    Arrays.fill(a1, 7);
    Arrays.fill(a2, 7);
    System.out.println(Arrays.equals(a1, a2));
    a2[3] = 11;
    System.out.println(Arrays.equals(a1, a2));

    String[] s1 = new String[5];
    Arrays.fill(s1, "Hi");
    String[] s2 = {"Hi", "Hi", "Hi", "Hi", "Hi"};
    System.out.println(Arrays.equals(s1, s2));
}

结果如下:

true
false
true

Vector 和 ArrayList

  • 两者都能够存储相同类型的对象,或者是有相同父类的对象,或者实现了公共接口的对象。
  • 两者都不能存储基本数据类型的数据,而是要将基本数据类型包裹到类里面才能存储到 Vector 或者 ArrayList 中。如 int 类型要包裹到 Integer 类型中才能存储。
  • 两者都是动态数组,容量都可以自动扩充
  • 添加元素的效率比较高;当空间已满,需要扩充的时候例外
  • Vector 是集合框架中的遗留类,旧线程安全
  • ArrayList 方法是非同步的,效率较高
  • 现在的 Java 提供了线程安全集合:Java.util.concurrent 包,所以现在 Vector 已经几乎被淘汰了
  • 任何集合类都可以使用同步包装器使其变为线程安全的。
    List synchArrayList = Collections.synchornisedList (new ArrayList ());

ArrayList 的构造方法

  • ArrayList():构造一个空表,长度默认为10
  • ArrayLsit (Collection c):用 c 中的元素为初始值构造一个表
  • ArrayList (int initialCapacity):创建一个空表,长度为 initialCapacity

ArrayList 的其它方法

【Java基础】06-Java集合框架_第4张图片
【Java基础】06-Java集合框架_第5张图片【Java基础】06-Java集合框架_第6张图片

遍历 Collection

通过 Enumeration 以及 Iterator 接口

  • Java 中的许多方法(如 elements() )都是返回 Enumeration 类型的对象,而不是返回 Collection 对象或者 其中元素的对象
  • Enumeration 接口不能用于 ArrayList 对象,而 Iterator 接口既可以用于 ArrayList 对象也可以用于 Vector 对象。
  • Iterator 接口是对 Enumeration 接口的改进,所以优先使用 Iterator 接口。

Iterator

  • 具有去除 Collection 对象中元素的能力
  • hasNext():判断后面是否还有元素
  • next():取得下一个元素
  • remove():去除下一个 Collection 对象中的元素

举例如下:

import java.util.Vector;
import java.util.Iterator;

public static void iteratorTester(){
    String[] num = {"one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine", "ten"};
    // 使用 asList() 将num包装成 ArrayList 类型
    Vector<String> avec = new Vector<>(java.util.Arrays.asList(num));
    System.out.println("Before Vector: " + avec);
    Iterator<String> it = avec.iterator();
    while(it.hasNext()){
        String s = (String)it.next();
        System.out.println(s);
        if(s.length()>4) it.remove();
    }
    System.out.println("After Vector: " + avec);
}

结果如下:

Before Vector: [one, two, three, four, five, six, seven, eight, nine, ten]
one
two
three
four
five
six
seven
eight
nine
ten
After Vector: [one, two, four, five, six, nine, ten]

使用增强的 for 循环

举例如下:

public static void forTester(){
    Vector<String > dayNames = new Vector();
    dayNames.add("Sunday"); dayNames.add("Monday");
    dayNames.add("Tuesday"); dayNames.add("Wednesday");
    dayNames.add("Thursday"); dayNames.add("Friday");
    dayNames.add("Saturday");

    for(String day: dayNames){
        System.out.println(day);
    }
}

使用聚集函数和 lambda 表达式

【Java基础】06-Java集合框架_第7张图片

Map 接口及其实现

Map 存储 key - value 类型的数据,通过 key 可以实现对值得快速存取和使用

有两个主要实现的类,包括 HashTable(java 1.0) 和HashMap(java 1.2)

Map 接口的查询方法

  • int size():返回 Map 中的元素个数
  • boolean isEmpty():如果为空,则返回 false,否则返回 true
  • boolean containsKey (Object key): 判断给定的参数是否为 Map 中的一个 key
  • boolean containsValue (Object key):判断给定参数是否为 Map 中的一个 value
  • Object get (Object key):返回关键字对应的值
  • Collection values():返回包含 Map 中所有的 value 组成的 Collection 对象
  • Set keySet():返回包含 Map 中所有 key 的 Set 对象
  • Set entrySet():返回包含 Map 中所有项的 Set 对象

Map 接口额修改方法

  • Object put (Object key, Object value):将给定的 key-value 加入到 Map 对象中。如果 key 在 Map 中已经存在,则原来的 value 会被新的 value 覆盖
  • void putAll (Map m):将参数 Map 对象中的项加入到调用的 Map 对象中去
  • Object remove (Object key):将关键字为 key 的项删除
  • void clear():将 Map 清空

Map 的一些基本概念

  • Map 中键的查找使用的是哈希函数
  • Map 的容量不是固定的,而是随着对象的加入可以自动扩充的
  • item(项):一个 key-value 对,其中双方都不能为空
  • load factor(装填因子):(表中已有的项数) / (表的容量)

HashMap 构造方法

【Java基础】06-Java集合框架_第8张图片

HashMap 的其它方法

【Java基础】06-Java集合框架_第9张图片
【Java基础】06-Java集合框架_第10张图片
【Java基础】06-Java集合框架_第11张图片

你可能感兴趣的:(Java,数据结构,java)