Collection接口
一、概述
二、Collection接口
Collection接口的方法:
boolean add(Object o): 向集合中添加一个元素,成功返回true。
boolean addAll(Collection c): 将集合c总所有元素添加至指定集合。
void clear(): 清空集合元素。
boolean contains(Object o ): 判断好似否包含该元素。
boolean contains(Collection c): 判断集合中是否包含集合c中所有元素。
Iterator iterator(): 返回一个iterator对象,用于遍历该集合。
boolean isEmpty():判断集合是否为空。
boolean remove(Object o): 删除集合中指定元素。
boolean removeAll(Collection c):删除集合c中所有元素。
int size(): 返回集合中元素个数。
Object[] toArray(): 将集合转换为数组。
Iterator接口
主要用于遍历Collection集合中的元素,Iterator必须依附于Collection对象,Iterator仅用于遍历集合,本身并不提供承装对象的能力。当使用Iterator遍历Collection集合时,Collection集合中元素不能被修改,但可以被删除。
boolean hasNext(): 如果仍有元素可以迭代,则返回 true。
Object next(): 应将Java迭代器认为是位于两个元素之间的。当调用next()时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
void remove(): 将会删除上次调用next()方法时返回的元素。如果需要删除指定位置上的元素,仍然需要先越过这个元素。
例如删除指定集合中第一个元素的方法:
Collection<Integer> c = new ArrayList<> ();
c.add(36);
c.add(12);
Iterator<Integer> it = c.iterator();
it.next();
it.remove();
注意:对于next方法和remove方法的调用具有相互依赖性,如果调用remove之前没有调用next是不合法的。只有对自然有序的集合使用迭代器添加元素才有意义,而像set类型,其中的元素完全无序。因此,在Iterator接口中就没有add方法。
三、Set接口
【Set接口】
Set里面元素是无序的,不允许包含相同元素。
Set集合中判断两个对象相同不使用==运算符,而是使用equals函数。
HashSet类
一种没有重复元素的无须集合。
HashSet是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素。HashSet实现原理:http://zhangshixi.iteye.com/blog/673143
HashSet是按Hash算法来存储集合中的元素,具有很好的存取和查询性能。
HashSet不能保证元素的排列顺序,顺序可能与添加顺序不同。
HashSet不是同步的。
HahsSet元素值可以是null。
HashSet判断两个元素相等的标准是:两个对象的equals()方法比较相等,并且两个对象的hashCode()方法返回值也相同。因此在把某个类的对象保存到HashSet集合中,重写这个类的equals方法返回true时,它们的hashCode方法返回值也相等。
LinkedHashSet类
一种可以记住元素插入次序的集。
LinkedHashSet与HashSet的不同之处在于,LinkedHashSet维护着一个双向链表,该链表定义了迭代顺序:插入顺序和访问顺序。
LinkedHashSet继承于HashSet,又基于LinkedHashMap来实现。LinkedHashSet底层构造了一个LinkedHashMap来实现,在相关操作上与父类HashSet相同。
LinkedHashSet也是根据元素的hashCode值来决定元素的存储位置,但它同时使用链表来维护元素的次序。当遍历LinkedHashSet时,LinkedHashSet将会按元素的添加顺序来访问集合中的元素。<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
TreeSet类
TreeSet可以确保集合元素处于排序状态。
TreeSet与HashSet采用hash算法决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储元素。
TreeSet支持两种排序方法:自然排序和定制排序。
对象的比较:
1)TreeSet如何知道希望元素怎样排列呢?在默认情况下,树集假定插入的元素实现了Comparable接口,该接口定义了一个方法:
int compareTo(T other); 如String类便实现了Comparable接口,它的compareTo方法依据字典序对字符串进行比较。
如果要将自定义的对象插入到TreeSet中,就必须实现Comparable接口,示例如下:
class Demo implements Comparable
{
public int x;
public int y;
public Demo(int x)
{
this.x = x;
}
public int compareTo(Object obj)
{
Demo other = (Demo)obj;
return this.x - other.x;
}
}
2)使用Comparable接口定义排序显然有其局限性。对于一个给定的类,只能实现这个接口一次。如果在一个集合中需要按x进行排序,在另一个集合中需要按y进行排序,该怎么办呢?另外,如果需要对一个类的对象进行排序,
而该类的创建者并没有实现Comparable接口,又该怎么办呢?这种情况下,可以通过将Comparator对象传递给TreeSet的构造器来告诉树集使用不同的比较方法。示例如下:
class Demo implements Comparable
{
public int x;
public int y;
public Demo()
{};
public Demo(int x,int y)
{
this.x = x;
this.y = y;
}
public int compareTo(Object obj)
{
Demo other = (Demo)obj;
return this.x - other.x;
}
}
public class Test{
public static void main(String[] args) throws Exception
{
Demo d1 = new Demo(2,6);
Demo d2 = new Demo(4,7);
Demo d3 = new Demo(5,3);
Demo d4 = new Demo(1,8);
Demo d5 = new Demo(9,0);
Set<Demo> set = new TreeSet<> (new Comparator<Demo> ()
{
public int compare(Demo d1,Demo d2)
{
return d1.y -d2.y;
}
});
set.add(d1);
set.add(d2);
set.add(d3);
set.add(d4);
set.add(d5);
for(Demo d : set)
System.out.println("x :" + d.x + "," + "y:" + d.y);
}
}
【EnumSet类】
EnumSet中所有元素都必须是指定枚举类型的枚举值。
EnumSet集合元素是有序的,EnumSet以枚举值在Enum类内的定义顺序决定集合元素的顺序。
EnumSet内部以向量的形式存储。
EnumSet集合不允许加入null值。
EnumSet没有构造器来实现,需通过它提供的static方法来创建EnumSet对象。
四、List接口
List接口方法:
List集合是元素有序、可重复的,每个元素都有对应索引。
与Set相比,List增加了根据索引来插入、替换和删除元素的方法。
List通过equals()方法返回true判断两个对象相等。
boolean add(E e):列表尾添加指定元素。
void add(int index,E element):在列表指定位置插入元素。
E get(int index):返回列表中指定位置元素。
int indexOf(Object o):返回列表中第一次出现的元素的索引,没有的话返回-1。
lastIndexOf(Object o):返回列表中最后出现的元素索引。
Iterator<E> iterator():按适当顺序返回迭代器。
ListIterator<E> listIterator():返回一个列表迭代器,以便用来访问列表中的元素。
size():返回列表中元素。
.......
ListIterator接口
List除了iterator()方法外,还提供了listIterator()方法。
ListIterator接口继承Iterator接口,提供了专门操作List方法:hasPrevious()、previous()、add()。
与Iterator相比,增加了向前迭代功能,还可通过add向List集合添加元素(Iterator只能删除元素)。
【ArrayList类和Vector类】
二者都是基于数组实现的List类,所以ArrayList类和Vector类封装了一个动态的、允许再分配的Object[]数组。
二者在用法上几乎完全相同,但Vector太古老,不建议使用。
【固定长度的List】
有一个操作数组工具类:Arrays,该类提供了asList(Object…a)方法,该方法可以把一个数组或者指定个数的对象转换成一个List集合,该List集合既不是ArrayList实现类的实例,也不是Vector实现类的实例,而是Arrays的内部类ArrayList的实例。
Arrays.ArrayList是一个固定长度的List集合,程序只能遍历集合里的元素,不可增加、删除。
五、Queue接口
Queue用于模拟队列这种数据结构。 队列可以让人们有效的在尾部添加一个元素,在头部删除一个元素。有两个端头的队列,即双端队列,可以让人们在头部和尾部同时添加或删除元素,但不支持在队列中间添加元素。它的两个实现类ArrayDeque类、LinkedList都提供了双端队列。
boolean add(E element)
boolean offer(E element)
如果队列没有满,将给定的元素添加到这个队列的尾部并返回true;如果队列满了,第一个方法将抛出异常,第二个方法返回false。
E remove()
E poll()
如果队列不空,删除并返回这个队列头部的元素。如果队列是空的,第一个方法抛出异常,第二个方法返回null。
E element()
E peek()
如果队列不空,返回队列头部的元素,但不删除。如果队列空,第一个方法抛出异常,第二个方法返回null。
Deque接口
是Queue接口的子接口,代表一个双端队列。
Deque定义了一些双端队列的方法,这些方法允许从两端来操作队列中元素。
这样,Deque不仅可以当成当成双端队列使用,还可以被当成栈来使用。
void addFirst(E element)
void addLast(E element)
boolean offerFirst(E element)
boolean offerLast(E element)
将给定的对象添加到双端队列的头部或尾部。如果队列满了,前面两个方法将抛出异常,后面两个方法返回false。
E removeFirst()
E removeLast()
E pollFirst()
E pollLast()
如果队列不空,删除并返回队列头部的元素。如果队列为空,前面两个方法将抛出异常,后面两个方法返回null。
E getFirst()
E getLast()
E peekFirst()
E peekLast()
如果队列为空,返回队列头部的元素,但不删除。如果队列空,前面两个方法将抛出异常,后面两个方法返回null。
PriorityQueue类
一种允许高效删除最小元素的集合。
PriorityQueue中的元素可以按照任意的顺序插入,却总是按照排序的顺序就行检索。无论何时调用remove方法,
总会获得当前优先级队列中最小的元素。优先级队列使用的数据结构是堆。
与TreeSet一样,一个优先级队列既可以保存实现了Comparable接口的类对象,也可以保存在构造器上提供比较器的对象。
使用优先级队列的典型示例是任务调度。每个任务都有优先级,任务以随机顺序添加到队列中。每当启动一个新的任务时,豆浆优
先级最高的任务从队列中删除(习惯上将"1"设置为最高优先级)。
【ArrayDeque类】
是Deque的一个典型实现类。
是一个基于数组实现的双端队列,创建队列时刻指定Object[]数组长度。
【LinkedList类】
是List接口的实现类,可根据索引来随机访问集合中元素,可被当成双端队列来使用。
是Deque接口的实现类,可被当成栈来使用。
Map接口
一、概述
Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,一组值用于保存Map里的value。Map中的key不允许重复。Map也被称为字典,或关联数组。
Set与Map之间关系密切:Map中的key没有顺序,key与key之间不能重复。从java源码来看,Java是先实现了Map,然后通过包装一个所有value都为null的Map就实现了Set。实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。
如果把Map里的所有value放在一起来看,它们类似于List:元素之间可以重复,每个元素可以根据索引来查找,只是Map中的索引不再是整数值,而是以另一个对象作为索引。
V get(Object key)
获取与键对应的值或对象
V put(K key,V value)
将键与对应的值关系插入到映射表中。如果这个键已经存在,新的value将会取代旧的value。
boolean containsKey(Object key)
如果在映射表中已经有这个键,返回true。
boolean containsValue(Object value)
如果在映射表中已经有这个值,返回true。
Set<Map.Entry<K, V>> entrySet()
返回Map.Entry对象的集视图。可以从这个集合中删除元素,同时也从映射表中删除了该元素。但不能添加元素。
Set<K> keySet()
返回映射表中所有键的集视图。可以从这个集合中删除元素,同时也从映射表中删除了该元素。但不能添加元素。
Collection<V> values()
返回映射表中所有值的集视图。可以从这个集合中删除元素,同时也从映射表中删除了该元素。但不能添加元素。
HashMap类
一种存储键/值关联的数据结构。
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。它的底层就是一个数组,数组中的每一项又是一个链表。当创建一个HashMap的时候,就会初始化一个
数组。HashMap的底层实现原理:http://zhangshixi.iteye.com/blog/672697
<strong>HashMap与Hashtable的关系</strong>
都是Map接口的典型实现类,二者关系类似ArrayList和Vector的关系。
HashMap可以使用null作为key或value,Hashtable不允许使用null作为key和value。
HashMap不是线程同步的,Hashtable是线程同步的。
HashMap的父类是AbstractMap类,Hashtable的父类是Dictionary类。
二者判断key相等的标准类似于HashSet:两个key通过equals()方法比较返回true,两个key的hashCode值也相同。
LinkedHashMap类
一种可以记住键/值项添加次序的映射表。当条目插入到表中,就会并入到双向链表中。
LinkedHashMap继承于HashMap,因而底层实现也是数组+链表,不同的是,LinkedHashMap的链表是一个双向链表,该链表定义了条目的顺序:插入顺序和访问顺序,默认是插入顺序。
LinkedHashMap的底层实现原理:http://zhangshixi.iteye.com/blog/673789
要实现访问顺序,可以调用构造方法:LinkedHashMap<K,V>(initialCapacity,loadFactor,true) 。 每次调用get或put,受到影响的条目将从当前的位置删除,并放到条目链表的尾部(只有条目在链表中的位置会受影响,而散列表中的同不会受影响。一个条目总位于与键散列码对应的桶中)。
访问顺序对于实现高速缓存的LRU(即:最近最少使用)原则十分重要。我们可能希望将访问频率高的元素放在内存中,而将近期最少使用的元素从内存中移除。我们可以让这一过程自动化。方法如下:
构造一个LinkedHashMap的子类,然后覆盖removeEldestEntry方法,每当方法返回true时,就添加一个新条目,从而导致删除eldest的条目。示例:
下面的高速缓存可以存放10个元素:
Map<K,V> cache = new MyLinkedHashMap<>(128,0.75f,true)
{
protected boolean removeEldestEntry(<Map.Entry<K,V>> eldest)
{
return size() > 10;
}
};
操作集合的工具类:Collections
是操作Set、List、Map等集合的工具类,实现对集合元素的排序、查找、修改等操作。