Java工程师知识树

Java基础-集合类-概述

2020-12-29  本文已影响0人  HughJin

Java工程师知识树 / Java基础


1.为什么要用集合类

Java编程思想中指出:

通常,程序总是根据运行时才知道的某些条件去创建新对象。
在此之前,不会知道所需对象的数量,甚至不知道确切的类型。
为解决这个普遍的编程问题,需要在任意时刻和任意位置创建任意数量的对象。
所以,就不能依靠创建命名的引用来持有每一个对象:
MyType aReference;
因为你不知道实际上会需要多少这样的引用。
大多数语言都提供某种方法来解决这个基本问题。Java有多种方式保存对象(应该说是对象的引用)。例如前面曾经学习过的数组,它是编译器支持的类型。数组是保存一组对象的最有效的方式,如果你想保存一组基本类型数据,也推荐使用这种方式。但是数组具有固定的尺寸, 而在更一般的情况中,你在写程序时并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,因此数组尺寸固定这一限制显得过于受限了。
Java实用类库还提供了一套相当完整的容器类来解决这个问题。
其中基本的类型是List、Set、Queue和Map。这些对象类型也称为集合类,但由于Java的类库中使用了Collection这个名字来指代该类库的一个特殊子集,所以我使用了范围更广的术语“容器”称呼它们。

解读:

  1. Java保存对象的方式有:

    • 数组【可以保存基本类型数据;数组尺寸固定;只能存储同一种类型的对象】

    • 集合类【不可以保存基本类型数据;在根本上都是数组,只是可以动态改变数组的大小;结合泛型可以存储多种类型的对象】

  2. Java中的容器指Collection、Map的统称

  3. 容器中存储的是对象的引用不是对象的值;数组在存储基本数据类型时是存储的对象的值

  4. 为什么使用集合? 可以封装一组对象的操作,降低编程难度,增加代码复用性,提高程序运行速度与质量。

2.集合中的概念

Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:

什么是集合框架?

集合框架是一个代表、操作集合的统一架构。所有的集合框架都包含以下几点:

3.集合的分类

整体体系图

Collection接口及其常用实现

Collection接口及其常用实现

Map接口及其常用实现

Map接口及其常用实现

附带Java集合最全结构展示图

4.常用集合类与对应数据结构

集合类是Java数据结构的实现。所以,从数据结构层面对比下集合类。

集合 接口/类 说明
Collection 接口 定义了集合的基本方法,
List 接口 元素有序,元素可重复。主要实现类:ArrayList,LinkedList,Vector。
Vector 线性表的数组实现
Stack 栈,Last in first out,继承自Vector
ArrayList 动态数组,源码底层维护着List的容量与实际长度
LinkedList 双向链表,此外它还实现了Deque,即也实现了Queue
Queue 接口 队列,First in first out
Deque 接口 双向队列,Deque继承自Queue,并增加了首尾两端的进出队列操作
Map 接口 一组元素结构为K、V型的集
HashMap 哈希数组+链表,通过哈希函数能够快速地找到元素,无冲突的情况下仅需访问一次 ;1.8后哈希数组+链表+红黑树
HashTable HashTable与HashMap的区别是其线程安全,同时它不允许K、V为null
TreeMap Map的二叉平衡树实现,根据K的hashcode排序
ConcurrentHashMap 线程安全的HashMap,HashTable的替代者
Set 接口 元素无序,元素不重复。主要实现类:HashSet,TreeSet,LinkedHashSet。
HashSet 内部使用HashMap实现,K对应E,V保存了一个Object
TreeSet 内部由TreeMap实现,K对应E,V保存了一个Object
LinkedHashSet 哈希表和链表的结合,且是一个双向链表;不重复且同时具有可预测的迭代顺序

5.容器操作使用

Collection增删改查与遍历

作为集合的一个根接口,定义了一组对象和它的子类可以实现的方法:


Collection.png

对集合的基础操作,比如 :

int size() 获取元素个数

boolean isEmpty() 是否个数为 0

boolean contains(Object element) 是否包含指定元素

boolean add(E element) 添加元素,成功时返回 true

boolean remove(Object element) 删除元素,成功时返回 true

Iterator<E> iterator() 获取迭代器

还有一些操作整个集合的方法,比如 :

boolean containsAll(Collection<?> c) 是否包含指定集合 c 的全部元素

boolean addAll(Collection<? extends E> c) 添加集合 c 中所有的元素到本集合中,如果集合有改变就返回 true

boolean removeAll(Collection<?> c) 删除本集合中和 c 集合中一致的元素,如果集合有改变就返回 true

boolean retainAll(Collection<?> c) 保留本集合中 c 集合中两者共有的,如果集合有改变就返回 true

void clear() 删除所有元素

还有对数组操作的方法:

Object[] toArray() 返回一个包含集合中所有元素的数组

<T> T[] toArray(T[] a) 返回一个包含集合中所有元素的数组,运行时根据集合元素的类型指定数组的类型

在 JDK 8 以后,Collection 接口还提供了从集合获取连续的或者并行流:

Stream<E> stream()

Stream<E> parallelStream()

List接口与Set接口实现Collection接口常用的方法有:

List接口
        List接口下的集合元素存储有序,可以重复。
        List的特有功能
          A:添加功能
              void add(int index, Object obj):在指定位置添加元素
          B:删除功能
              Object remove(int index):根据指定索引删除元素,并把删除的元素返回。
          C:修改功能
              Object set(int index, Object obj):把指定索引位置的元素修改为指定的值,返回修改前的值。
          D:获取功能
              int indexOf(Object o):返回指定元素在集合中第一次出现的索引
              Object get(int index):获取指定位置的元素
              ListIterator listIterator():列表迭代器
          E:截取功能
              List subList(int fromIndex, int toIndex):截取集合。

  Set 接口
          Set接口下的元素无序,不可以重复。其下面常用有HashSet和TreeSet。
          HashSet
           底层数据结构是哈希表,线程不安全,效率高。
           保证唯一性依赖两个方法:hashCode()和equals()。
           顺序:
                   判断hashCode()值是否相同。
                   相同:继续走equals(),看返回值
                               如果true:就不添加到集合。
                               如果false:就添加到集合。
                   不同:就添加到集合。
          TreeSet
            底层数据结构是二叉树,线程不安全,效率高。
            保证元素唯一性的方法时根据返回值是否是0。
            保证排序的两种方式:
                    自然排序(元素具备比较性):实现Comparable接口
                    比较器排序(集合具备比较性):实现Comparator接口

遍历 Collection 的几种方式:

for-each语法
Collection<Person> persons = new ArrayList<Person>();
for (Person person : persons) { 
    System.out.println(person.name);  
}  
使用 Iterator 迭代器
Collection<Person> persons = new ArrayList<Person>();
Iterator iterator = persons.iterator();
while (iterator.hasNext) { 
    System.out.println(iterator.next);  
}  
使用 aggregate operations 聚合操作
Collection<Person> persons = new ArrayList<Person>();
persons
    .stream()
    .forEach(new Consumer<Person>() {  
        @Override  
        public void accept(Person person) {  
            System.out.println(person.name);  
        }  
}); 

Map增删改查与遍历

map是一个键值对形式的集合。它的元素都是有键和值组成。Map的键(key)是唯一的,值(value)可以重复。

Map的功能:

A:添加功能
V put(K key ,V value) :当key在集合中不存在是,添加元素;当key存在时替换元素

B:判断功能
boolean containsKey (Object key) :判断指定的键是否在集合中存在
Boolean containsValue(Object value):判断指定的值是否在集合中存在
Boolean isEmpty() :判断集合是否为空

C:删除功能
Void clear():清除所有键值对数据

D:获取功能
Object get (Object key) :根据键获取值
Set<K> keyset(): 所有键的集合
Collection<V>values() :所有值的集合

E:长度功能
Int size()

Map常用的有HashMap、HashTable和TreeMap,遍历常用有3种方法:

Map<String, Object>map = new HashMap<String, Object>();
map.put(“test1”, object1);
……
map.put(“testn” , objectn);

(1).Map的values()方法可以获取Map值的集合:

Iterator it = map.values().iterator(); 
while(it.hasNext()){ 
  Object obj = it.next(); 
} 

(2).Map的keySet方法可以获取Map键的Set集合:

Set<String> keys = map.keySet(); 
for(Iterator it = key.iterator(); it.hasNext(); ){ 
  String key = it.next(); 
  Object obj = map.get(key); 
} 

(3).通过Map.entrySet使用iterator遍历key和value

Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
     Map.Entry<Integer, String> entry = it.next();
     System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}

(4).通过Map.entrySet遍历key和value,推荐,尤其是容量大时

for (Map.Entry<Integer, String> entry : map.entrySet()) {
    //entry.getKey() ;entry.getValue(); 
    System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}

上一篇 下一篇

猜你喜欢

热点阅读