Java——集合

目录:

1.Collection

2.Iterator接口

3.Set集合

4.List集合

5.Queue

6.Map

7.collections工具类

Java集合大致可分为Set、List、Queue和Map四种体系。其中Set代表无序、不可重复的集合;List代表有序、重复的集合;而Map则代表具有映射关系的集合;Java5新增的Queue集合,代表一种队列集合的体现。

Java集合类主要由两个接口派生而出:Collection和Map。

扫描二维码关注公众号,回复: 1234470 查看本文章

接下来按照顺序对上述的集合进行分析。

1.Collection:

Collection作为List、Set和Queue接口的父接口,它定义的方法也可操作他的子接口。

常用方法如下:

boolean add(Object o):

boolean addAll(Collection c):

boolean contains(Object o):

Iterater iterator():返回一个Iterator对象,用于遍历集合里的元素

boolean remove(Object o):

int size():

2.Iterator接口和遍历集合:

使用lambda表达式遍历集合(Collection的父接口Iterable接口提供了forEach(Consumer action)默认方法):

Collection books=new HashSet();
...
...
...
//调用forEach()方法遍历集合
books.forEach(obj->System.out.println("迭代集合元素:"+obj));

Ierator遍历集合元素:Iterator接口也是Java集合框架的成员,但是它与Collection、Map不同,它主要用于遍历。

Iterator接口方法:

boolean hasNext():

Object next():

void remove():删除集合里上一次next方法返回的元素

void forEachRemaining(Consumer action):这是java8为Iterator新增的默认方法,该方法可使用lambda表达式来遍历元素。

Iterator it=books.iterator();
while(it,hasNext()){
    String book=(String)it.next();

    it.remove();//正确
    //如果使用books.remove(book);则抛出异常,因为Iterator迭代过程中不可集合元素
}

使用lambda表达式遍历Iterator

使用foreach循环遍历集合元素

3.Set集合

Set集合与Collection基本相同,没有提供任何额外的方法,实际Set就是Collection,只是行为略有不同(Set不允许包含重复元素)。主要有几个实现类:HashSet、LinkedHashSet、TreeSet和EnumSet。

①HashSet类

特点:①不能保证元素排列顺序。②不是同步的。③集合元素可以是null。

HashSet中根据hashCode()用“”装元素(数组),如果一个“桶”中有多个元素则用链表储存。

hashCode()返回值应该和equals()返回值相同。

重写hashCode()方法的基本规则:最主要的是:对象中用作equals()方法比较标准的实例变量,都用该用于计算hashCode值。

尽量不要修改参与计算hashCode()、equals()的变量,否则会导师HashSet无法正确操作这些集合元素。

②LinkedHashSet类

继承HashSet类。

特点:按照元素的添加顺序来存储集合里的元素。

③TreeSet类:

继承SortedSet类。

特点:按照元素大小排序。(红黑树); 修改放入的元素会导致错误。

支持两种排序方法:

①自然排序:添加的对象必须实现了Comparable接口;必须是同一类的对象。

②定制排序:需要在创建集合对象是,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。Comparator是函数式接口,可使用lambda表达式,如下

TreeSet ts=new TreeSet((o1,o2)->
{
M m1=(M)o1;
M m2=(M)o2;
//根据M对象的age属性来决定大小,age越大,M对象反而越小
return m1.age>m2.age?-1:m1.age<m2.age?1:0;
});

④EnumSet类

EnumSet是一个专为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式的指定。

特点:按照枚举值在Enum类中定义顺序来决定;性能最佳。

EnumSet没有构造器,通过类方法来创建EnumSet对象。

//创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
EnumSet es1=EnumSet.allOf(Senson.class);

EnumSet es2=EnumSet.allnoneOf(Senson.class);

es2.add(Senson.WINTER);

性能分析:

HashSet和TreeSet是Set的两个典型实现。HashSet的性能总是比TreeSet好,特别是最常用的(添加查询等操作)。因为TreeSet需要额外的红黑树算法来保持次序。除非,当需要一个保持排序的Set时才会使用TreeSet。

LinkedHashSet,对于普通插入删除操作,比HashSet慢(因为为了维护链表),但是遍历速度回更快,因为基于链表。

EnumSet是性能最好的,因为他只能保存同一个枚举类的枚举值作为集合元素。

他们都是线程不安全的。

4.List集合

list集合代表一个元素有序、可重复的集合。

常用方法:(相对于Collection多了一些对于index操作的方法)

void add(int index,Object element):

Object get(int index):

Object remove(int index)

Object set(int index,Object element):

void sort(Comparator c):

List books=new ArrayList();

books.sort((o1,o2)->((String)o1).length()-((String)o2).length());
//字符串长度越长,字符串越大

ListIterator接口在Iterator接口基础上增加了如下方法:(增加了向前迭代的功能)

boolean hasPrevious():

Object previous():

void add(Object o):

ArrayList和Vector实现类:

都是基于数组实现的。

都可以自动增加程度,但是如果知道需要添加大量元素时,使用ensureCapacity(int minCapacity)方法一次性的增加initialCapacity,从而减少重分配的次数,可以大大提高性能。

区别ArrayList线程不安全,Vector线程安全;Vector已经过时,他的子类Stack也过时,实现栈功能,一般推荐使用Arraydeque。

注意Array.ArrayList与List.ArrayList不同,前者为固定长度且不支持增删元素。

5.Queue集合

Queue接口用于模拟队列这种数据结构。先进先出(FIFO).

方法:

void add(Object e):将指定元素加入此队列的尾部。

bolean offer(Object e):将指定元素加入此队列尾部,当时用有容量限制的队列时,此方法通常比add方法更好。

Object peek():获取队列头部的元素。为空返回null。

Object poll():获取队列头部的元素,并删除该元素,空返回null。

Object remove():获取头部元素,并删除该元素。

Queue接口有一个PriorityQueue实现类,除此之类Queue还有一个Deque接口,Deque接口代表一个“双端队列”,所以Deque可以当成队列或者栈使用。java为deque提供了arraydeque和linkedlist两个实现类。

①PriorityQueue实现类

PriorityQueue是一个比较标准的队列实现类:是“比较”而不是绝对准确的原因是,它保存队列元素的顺序并不是按照元素加入顺序,而是按队列元素的大小进行重新排序。

排序方式:自然排序;定制排序。

②Deque接口和ArrayDeque

Deque为双端队列。Deque底层数组长度为16,也会自动调整数组大小。

栈:push peek pop  

队列:offer peek  poll

③LinkedList实现类

LinkedList是List的一个实现类,也实现了Deque接口,可实现List集合,双端队列,栈的功能。

但是与ArrayList和ArrayDeque实现机制完全不同。ArrayList和ArrayDeque基于数组实现,因此随机访问集合元素时有较好的性能;而LinkedList基于链表实现,随机访问性能较差,但是插入删除元素时的性能比较出色。

对于所有基于数组的集合实现,使用随机访问的性能比使用Iterator迭代访问的性能要好。

性能分析:

比较ArrayList和LinkedList性能即比较数组和链表的性能区别。

ArrayList(数组):随机访问性能好。  遍历使用随机访问方法get性能更好

LinkedList(链表):插入删除操作性能好。   遍历使用迭代器性能更好

总体来说ArrayList性能更好。

6.java8增强的Map集合

Map的key不允许重复。

Set可看做一个value为null的Map,所以Set、Map大部分操作都相似。

方法:

Object get(Object key):

Set keySet():返回该map中所有key组成的set集合。

Object put(Object key,Object value):

Object remove(Object key):

Map中包括一个内部类Entry,该类中封装了key-value。

①HashMap和Hashtable

类似于HashSet和Vector。

HashMap允许null作为key或者value,Hashtable则不允许。

hashCode和equals都根据key计算或比较。

②LinkedHashMap实现类

类似于LinkedHashSet,保持插入顺序。

用链表维护,性能低于HashMap,但是迭代访问时具有更好的性能。

③使用Properties读写属性文件

priperties类可以把Map对象和属性文件关联起来,从来吧Map对象中的key-Value对写入属性文件中。

properties相当于一个key、value都是String类型的Map。

④SortedMap接口和TreeMap实现类

类似于SortedSet接口和TreeSet实现类。

排序方式:自然排序,定制排序。

⑤WeakHashMap实现类

HashMap的key是强引用;WeakHashMap的key是弱引用。

⑥IdentityHashMap实现类

这个map实现类的实现机制与HashMap基本相似,但它在处理两个key相等时比较独特:在IdentityHashMap中,当且仅当两个Key严格相等(key1==key2)时,才认为两个相等;对于普通HashMap来说,只要key1和key2通过equals方法比较返回true,且他们的hashCode值相等即可。

public class IdentityHashMapTest {
	public static void main(String[] args) {

		IdentityHashMap ihm=new IdentityHashMap<>();

		//下面两行代码将会向IdentityHashMap对象中添加两个key-value对
		ihm.put(new String("语文"), 89);
		ihm.put(new String("语文"), 89);    //两个key具有不同的引用

		//下面两行代码只会向IdentityHashMap对象中添加一个Key-value对
		ihm.put("java",93);
		ihm.put("java",98);                //“java”为直接量

		System.out.println(ihm);
	}
}

性能分析:类似于Set。

7.操作集合的工具类:Collections

排序:

Collections提供了如下常用的类方法用于对list集合元素进行排序:

void reverse(List list):

void shuffle(List list):

void sort(List list):

void sort(List list,Comparator c):

void swap(List list,int i,int j):

Collections.sort(nums);//用法

查找替换:

int binarySearch(List list,Object key):

Object max(Collection coll):

同步控制:

Collections类中提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

如:

List list=Collections.synchronizedList(new ArrayList());

设置不可变集合:

Collections提供了如下三类方法来返回一个不可变集合。

emptyXxx():

singletonXxx():

unmodifiableXxx():

使用如下:

//创建一个空的、不可变得list对象
List unmodifiableList=Collections.emptyList();

//创建一个只有一个元素,且不可改变的set对象
Set unmodifiableSet=Collections.singleton("qqqqq");

//返回普通Map对象对应的不可变版本
Map unmodifiableMap=Collections.unmodiableMap(scores);//scores为一个普通Map对象

Java9新增的不可变集合:

程序直接调用Set、List、Map的of()方法即可创建包含N个元素的不可变集合

适用如下:

//创建包含3个元素的Set集合,list类似
Set set=Set.of("Java","qqqq","Go");

//法一:创建包含三个key-value对的集合
Map map=Map.of("语文",89,"数学",85,"英语",92);

//法一:创建包含三个key-value对的集合
Map map2=Map.ofEntris(Map.entry("语文",89),Map.entry("数学",85),Map.entry("英语",92));

繁琐的接口:Enumeration

是Iterator迭代器的“古老版本”。但为了支持原来的程序,不能删除。

告诫我们,加入任何规则都必须慎之又慎,因为以后无法删除规则。

注:

从集合中取出的元素都是object,所以必须进行强制类型转换。

不要随便修改集合元素,会导致基于hash的访问错误。

猜你喜欢

转载自my.oschina.net/u/3786691/blog/1649372