Java基础之-----集合框架

来源:互联网 发布:史丹利快报的淘宝店 编辑:程序博客网 时间:2024/04/25 07:20

Java集合框架包括:— interfaces, implementations, aggregate operations, and algorithms (接口,实现,聚合操作和算法),这些组成了Java集合框架的核心。其中:

  • 接口是Java集合框架的灵魂
  • 实现介绍了Java一些常用的集合实现
  • 聚合操作是JDK8提供的新功能,能够方便的实现集合类型的转换
  • 算法定义了Java用于集合操作的多态算法

集合简介

集合,有时也称作容器,是用来存储、检索、操作和传递集合数据的。它代表同类数据的一个集合。

集合框架是用来操作集合的一个统一的框架,所有的集合框架都包括接口、实现和算法三部分。另外JDK8还新添加了聚合操作,提供了更加强大的功能。

接口是代表集合的抽象数据类型,,它使得对集合的操作独立于集合的具体实现,所有的接口通常形成层级关系。

实现是接口的具体实现类型。本质上,他们是可重用的数据类型

算法是用来对实现接口的对象执行有用的操作。算法通常具有多态行为,本质上他们是可重用的方法。

接口

核心接口是Java 集合框架的基础,Java的核心集合接口封装了很多不同类型的Java集合,他们组成了一个层级关系。如下所示:

可以看到,Java的核心集合接口,由两颗不同的层级树组成。

Java集合接口都是泛型,所以在使用的时候一定要指定接口所操作的类型,以便于编译器进行编译时类型检查,避免运行时错误。

可以看出,这个层级关系分为两个不同的树:Collection和Map,下面对这两个不同的树进行详细的介绍。

Collection :是Java集合的根。是所有集合实现的最小公分母。

Set :是不包含重复元素的集合,它是对数学上集合概念的建模。

SortedSet :它是一个按升序管理元素的set,比如单词表

List :是一个有序的集合,通常称为序列,允许包含重复元素。

Queue :是一个用来在处理前保存数据的集合,它除了集合的操作外,还有一些额外的操作:插入、删除、检查等。通常Queue采用先进先出的顺序排列元素但不是必须的。每一个Queue 的实现,都需要指定它的排序属性,用来定义如何排序。在FIFO Queue 里,总是在头部删除,在尾部插入。不管Queue 是如何排序,总是在头部执行remov和poll操作。

Deque :也是用来保存将要处理的数据的,除了集合操作外,添加了插入、删除、检查等操作。Deque 既可以是FIFO,也可以是LIFO的,和Queue 不同的是,Deque的两端都可以执行插入删除和检索操作。

Map :是一个将Key映射到value的对象,不允许有重复的key,并且一个key最多只能有一个value与之对应。

SortedMap :是一个按升序方式管理键值对的Map。

Set

Set是一个不允许有重复元素的Collection,它只有从Collection继承过来的接口,同时添加了不允许重复元素的限制,加强了对equals()和hashCode()的定义,允许比较两个不同的实现类型的set,当且仅当两个set含有一样的元素。

Java提供了三种常用的Set的实现类:HashSet、TreeSet、LinkedHashSet。

HashSet:用HashTable存储元素,有最好的性能,但是不保证一致的迭代顺序

TreeSet:用红黑树存储元素,按值排列元素,比HashSet慢,

LinkedHashSet:用一个链表实现hash table,以插入顺序排列元素。性能和HashSet差不多。

需要主要的是HashSet的迭代和元素的总个数和Set的大小线性相关,初始大小太大,浪费了内存,太大,浪费时间。如果不指定,默认大小是16,而且的内部处理是去最接近的2的整数次幂,另外,Hashset有一个调节参数叫装填因子。LinkedHashSet有装填因子,而TreeSet没有。

Java还提供了两种特殊的实现: EnumSet 和 CopyOnWriteArraySet.

set的基本操作

Java提供了一些set的基本操作,包括:size、isEmpty 、add 、remove 、iterator。这些操作都是基本的操作,功能也一目了然。

Set的块操作

set的块操作实际执行的是集合的代数运算:包含,交并补等操作

s1.containsAll(s2):包含

s1.addAll(s2)并集

s1.retainAll(s2)交集

s1.removeAll(s2)补集

注意:对集合进行交并补操作的时候,会改变s1,s1就是操作后的结果,也就是这些操作都有副作用。为了不改变s1,应该对s1的副本做操作。如下:

Set<Type> union = new HashSet<Type>(s1);union.addAll(s2);Set<Type> intersection = new HashSet<Type>(s1);intersection.retainAll(s2);Set<Type> difference = new HashSet<Type>(s1);difference.removeAll(s2);

这样就避免了操作的副作用。

另外,利用以上提供的块操作,我们还可以对集合求对称差集:集合的并集和集合的交集的差集就是集合的对称差集。代码如下:

Set<Type> symmetricDiff = new HashSet<Type>(s1);symmetricDiff.addAll(s2);Set<Type> tmp = new HashSet<Type>(s1);tmp.retainAll(s2);symmetricDiff.removeAll(tmp);

List

List是一个有序的Collection,也称作序列,除了Colection定义的操作外,它还添加了以下几种类型的操作

按位存取 按元素在list中的数值位置访问元素,包括:get, set, add, addAll, and remove.

其中set 和 remove返回的是操作之前的值。

定位 返回指定对象返回其在list中的位置,包括:indexOf 、 lastIndexOf.

迭代 利用list的线性特性,继承了迭代器的语法,包括: listIterator 返回的是一个ListIterator,继承自Iterator,但同时它增加了向前迭代的功能,同时也支持按位访问 范围视图 获得list任意长度的子序列,包括:sublist 对sublist的修改同样也会作用于List本身

Java提供了三种常用的List:

ArrayList:它的优点是能够实现元素的随机访问,能够利用System.arraycopy同时移动多个元素 ,它有调节参数,线程不安全

LinkedList:当需要频繁的在list的头部添加元素或者平凡的通过迭代器删除元素时,可以考虑用LInkedList。没有调节参数,同时实现了Queue接口,线程不安全 Vector:线程安全的,当需要考虑同步的时候,使用

同样,List也提高了equals 和 hashCode的要求,这样两个不同实现的list可以做逻辑上的比较操作,当且仅当两个list含有相同的元素而且顺序一样,两个list才相等。

Queue

用来保存预处理的元素,除了Collection的操作,还添加了插入、删除、检查操作,如下:

public interface Queue<E> extends Collection<E> {    boolean add(E e);    boolean offer(E e);    E remove();    E poll();    E element();    E peek();}

所有的这六个方法可以分为两种形式:

  1. 操作失败后抛出异常
  2. 操作失败后返回特殊的值

通常Queue采用先进先出的顺序排列元素但不是必须的。每一个Queue 的实现,都需要指定它的排序属性,用来定义如何排序。在FIFO Queue 里,总是在头部删除,在尾部插入。不同的队列可能采取不同的排序规则。不管Queue 是如何排序,总是在头部执行remov和poll操作。

一些Queue会限制元素的个数,这样的队列是有限的,java.util.concurrent 里实现的队列都是有限的,java.util 里的实现不是的。

add 和offer

用于执行入队操作。

add用于向队列插入元素,当它用于向有界队列插入元素时,如果越界,则会抛出IllegalStateException

offer:专门用来向有界队列插入元素,不同于add是,如果越界,则返回false

remove和poll

用于执行出队操作,移除并返回队列头部的元素,但是具体哪个元素被移除,和队列的排序策略有关。两者不同之处是,当队列为空时,前者抛出NoSuchElementException,后者返回null

element和peek

返回但不移除队列头部的元素,二者的区别是,当队列为空时,前者抛出NoSuchElementException,后者返回null

队列默认是不允许插入null的,但是LinkedList实现确允许插入null。尽管如此,应当避免这种用法,因为pool和peek会使用这个特殊值。

Queue没有实现基于元素的equals和hashCode,而是继承自Object。同时也没有实现队列阻塞方法,而是在 java.util.concurrent.BlockingQueue中定义了阻塞方法,这个接口继承自Queue,这在并发编程中需要用到。

实现:LinkedList和PriorityQueue

Deque

双端队列是一个支持在两端执行插入删除操作的线性集合,它是一个比Stack和Queue丰富的抽象数据类型,因为它同时实现了Stack和Queue的功能。它提供了在两端进程插入、删除和检查元素的接口。

ArrayDeque和LinkedList都是Deque的实现类

它既可以当做FIFO队列又可以当做LIFO队列。

Deque提供了12个方法,用于对两端元素进行操作,如下:

这些方法的区别是,在操作失败是有些抛出异常,有些返回特定的值,这个和Queue类似。

同时,Deque还提供removeFirstOccurence和removeLastOccurence,这两个方法顾名思义,当不存在时返回false。

Java提供了两种常用的Deque:

LinkedList:比ArrayDeque灵活,允许插入null,但是插入和删除效率差,耗内存

ArrayDeque:性能好,节约内存,但是不允许插入null。

Map

是一个将Key映射成Value的对象,一个map不能含有重复的key,一个key最多对应一个value,它是对数学函数的抽象建模。

它主要提供

  • 基本操作:put, get, remove, containsKey, containsValue, size,empty
  • 块操作:putAll, clear
  • 集合视图: keySet, entrySet, values

Java提供了三种常用的Map的实现类: HashMap, TreeMap, and LinkedHashMap. 和Set的常用实现一样 HashMap:key 的顺序不确定,性能最好 TreeMap :实现了key按值的升序排列,性能比HashMap差 LinkedHashMap. key按put的先后顺序排列,性能和HashMap差不多。需要注意的是,LinkedHashMap和LinkedHashSet不同,首先,它的排序顺序是按访问的频率的高低,访问频率越低,会被排到后面,同时,LinkedHashMap提供了removeEldestEntry(),这样可以通过重写这个方法,当添加新的元素的时候,自动的删除陈旧的元素,利用它可以实现缓存cache。

同样,Map也提高了equals 和 hashCode的要求,实现不同Map实现的比较,两个map相等,当且仅当他们的映射关系相同。

对象的排序

当我们需要对一个List的元素进行排序时,可以采用如下做法

Collections.sort(list);//list是一个List类型对象

但是前提是list里的元素实现了Comparable接口,如果没有实现Comparable,那么,会抛出ClassCastException。Java提供了一些实现了Comparable接口的类。

当需要比较两个对象时,可以使用:

public interface Comparator<T> {int compare(T o1, T o2);}

接口

SortedSet

该类提供了按某种方式排序的Set。

public interface SortedSet<E> extends Set<E> {    Comparator<? super E> comparator();    //range View    SortedSet<E> subSet(E fromElement, E toElement);    SortedSet<E> headSet(E toElement);    SortedSet<E> tailSet(E fromElement);    //end point    E first();    E last();}

SortedMap

和SoredSet一样,这里就不说了。

0 1
原创粉丝点击