java 集合类
Posted qqiua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 集合类相关的知识,希望对你有一定的参考价值。
为了保存数目不确定的对象,JDK中提供了集合类(又称容器类),这些类可以存储任意类型的对象,并且长度可变,所有的集合类都位于java.util包中,在使用时需要导入该包,否则会出现异常。
Java集合类
集合按照存储结构可以分为两大类,分别是单列集合(Collection)和双列集合(Map),这两种集合的特点如下所示:
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。其中,List的特点是元素有序,元素可重复;Set的特点是元素无序,而且不可重复。List接口的实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet环绕TreeSet。
- Map:双列集合类的根接口,用于存储具有键(Key)、值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的key找到对应的Value。Map接口的主要实现类有HashMap和TreeMap。
List接口
在List集合中可以出现相同的元素,所有的元素是以一种线性方式进行存储的,因此使用此集合能够精确地控制每个元素插入的位置,用户能够使用索引访问List中的元素。另外,List集合还有一个特点就是元素有序,即元素的存入和取出顺序一致。
ArrayList集合
ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。
ArrayList的继承关系
java.lang.Object
? java.util.AbstractCollection<E>
? java.util.AbstractList<E>
? java.util.ArrayList<E>
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
ArrayList API
1 // Collection中定义的API 2 boolean add(E object) 3 boolean addAll(Collection<? extends E> collection) 4 void clear() 5 boolean contains(Object object) 6 boolean containsAll(Collection<?> collection) 7 boolean equals(Object object) 8 int hashCode() 9 boolean isEmpty() 10 Iterator<E> iterator() 11 boolean remove(Object object) 12 boolean removeAll(Collection<?> collection) 13 boolean retainAll(Collection<?> collection) 14 int size() 15 <T> T[] toArray(T[] array) 16 Object[] toArray() 17 // AbstractCollection中定义的API 18 void add(int location, E object) 19 boolean addAll(int location, Collection<? extends E> collection) 20 E get(int location) 21 int indexOf(Object object) 22 int lastIndexOf(Object object) 23 ListIterator<E> listIterator(int location) 24 ListIterator<E> listIterator() 25 E remove(int location) 26 E set(int location, E object) 27 List<E> subList(int start, int end) 28 // ArrayList新增的API 29 Object clone() 30 void ensureCapacity(int minimumCapacity) 31 void trimToSize() 32 void removeRange(int fromIndex, int toIndex)
ArrayList的toArray
ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法:
(1)list.toArray();
(2)list.toArray(T[] a);
对于第一个重载方法,是将list直接转为Object[] 数组;
第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
ArrayList 三种遍历方式
(1)第一种,通过迭代器遍历。即通过Iterator去遍历。
Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
(2) 第二种,随机访问,通过索引值去遍历。
由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。
Integer value = null;
int size = list.size();
for (int i=0; i<size; i++) {
value = (Integer)list.get(i);
}
(3)第三种,foreach循环遍历。如下:
Integer value = null;
for (Integer integ:list) {
value = integ;
}
使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低
Set接口
Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值确定元素在集合中的存储位置,因此具有良好的存取和查找性能。TreeSet是以二叉排序树的方式存储元素,他可以实现对几个元素进行排序。
HashSet集合
HashSet结合之所以能确保不出现重复的元素,是因为在想Set中添加对象时,会西安调用次对象所在类的hashCode()方法,计算此对象的哈希值,次哈希值决定了此对象在Set中的存储对象,再通过equals()比较这两个对象是否相同,如果相同,则后一个对象就不能再添加进来。
Map接口
HashMap集合
HashMap集合是基于哈希表的Map接口的实现,它用于存储键值映射关系,但不保证映射的顺序。
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子是 0.75, 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。
HashMap的继承关系
java.lang.Object
? java.util.AbstractMap<K, V>
? java.util.HashMap<K, V>
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable { }
(01) HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。
(02) HashMap是通过"拉链法"实现的哈希表。它包括几个重要的成员变量:table, size, threshold, loadFactor, modCount。
table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。
size是HashMap的大小,它是HashMap保存的键值对的数量。
threshold是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值="容量*加载因子",当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。
loadFactor就是加载因子。
modCount是用来实现fail-fast机制的。
HashMap的整体结构
简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。
HashMap遍历方式
(1) 遍历HashMap的键值对
第一步:根据entrySet()获取HashMap的“键值对”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
1 // 假设map是HashMap对象
2 // map中的key是String类型,value是Integer类型
3 Integer integ = null;
4 Iterator iter = map.entrySet().iterator();
5 while(iter.hasNext()) {
6 Map.Entry entry = (Map.Entry)iter.next();
7 // 获取key
8 key = (String)entry.getKey();
9 // 获取value
10 integ = (Integer)entry.getValue();
(2)遍历HashMap的键
第一步:根据keySet()获取HashMap的“键”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// 获取key
key = (String)iter.next();
// 根据key,获取value
integ = (Integer)map.get(key);
(3)遍历HashMap的值
第一步:根据value()获取HashMap的“值”的集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
Properties集合
Properties主要用于存储字符串类型的键和值,由于Properties类实现了Map接口,因此,Properties类本质上是一种简单的Map集合。在实际开发中,经常使用Properties几个存取应用的配置项。
(1)setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。
(2)getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
(3) load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。通过对指定的文件进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。
(4)store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。
(5) clear (),清除所有装载的 键 - 值对。该方法在基类中提供。
Collection 和 Collections的区别:
Collection是一个集合的接口。它提供了对集合对象进行基本操作的通用方法。实现该接口的类主要有List和Set,该接口的设计目标是为各种具体的集合提供最大化的同一操作方式。
Collections是针对集合类的一个包装类,它提供了一系列静态方法实现对各种集合的搜索、排序以及线程安全等操作,其中大部分方法用于处理线性表。Collection类不能实例化,如同一个工具类,服务于Collection框架。如果在使用Collections类的方法时,对用Collection的对象null,则这些方法都会抛出NullPointException。
参考:
http://www.cnblogs.com/skywang12345/p/3308556.html
http://www.cnblogs.com/skywang12345/p/3310835.html
https://www.cnblogs.com/chengxiao/p/6059914.html
2018-10-03 20:46:17
以上是关于java 集合类的主要内容,如果未能解决你的问题,请参考以下文章