Collection接口
API文档中的描述是:public interface Collection<E> extends Iterable<E>.
Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。
常用的方法
boolean add(E e);//向容器中添加指定的元素 Iterator<E> iterator();//返回能够遍历当前集合中所有元素的迭代器 boolean contains(Object o);//判断容器中是否包含指定的元素 boolean remove(Object o);//删除容器中的元素o,如果容器中包含o,返回true int size();//返回容器中元素的个数 Object[] toArray();//返回包含此容器中所有元素的数组
- Set接口
Set顾名思义为集合,即不允许出现相同的元素。由于其内部存储结构的特点,不区分元素的顺序。
- HashSet
实现了Set接口的类,内部使用HashMap来存储数据,数据存储在HashMap的key中,value都是同一个默认值。HashSet有四种构造方法:
HashSet( ):构造一个空的Set,底层HashMap实例的默认初始容量为16,装载因子是0.75
HashSet(Collection<? extends E> c):构造一个包含指定collection中的元素的新Set
HashSet(int initialCapacity):构造一个指定初始容量和默认装载因子0.75的新Set
HashSet(int initialCapacity, float loadFactor):构造一个指定容量和指定装载因子的新的Set
import java.util.*; public class HashTest { @SuppressWarnings("unchecked") public static void main(String[] args){ HashSet hashSet1 = new HashSet(); hashSet1.add(1); hashSet1.add("abc"); hashSet1.add("abc"); int[] arr = new int[]{1,2,3}; hashSet1.add(arr); HashTest ht = new HashTest(); Apple apple1 = ht.new Apple(); hashSet1.add(apple1); Iterator it = hashSet1.iterator(); System.out.println(hashSet1.size()); while(it.hasNext()){ Object ob = it.next(); if(ob instanceof Integer) System.out.println("Integer:" + ob); if(ob instanceof String) System.out.println("String:" + ob); if(ob instanceof Apple) System.out.println("Apple:" + ob); if(ob instanceof int[]){ System.out.print("int[]:"); System.out.println(Arrays.toString(arr)); } } } public class Apple{ static final int id = 1; @Override public String toString() { return "Apple " + id; } } }
输出结果:
4
Integer:1
String:abc
int[]:[1, 2, 3]
Apple:Apple 1
- LinkedHashSet
LinkedHashSet继承自HashSet,唯一的区别是LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。类HashSet和LinkedHashSet都是接口Set的实现,两者都不能保存重复的数据。主要区别是HashSet不保证集合中元素的顺序,即不能保证迭代的顺序与插入的顺序一致。而LinkedHashSet按照元素插入的顺序进行迭代,即迭代输出的顺序与插入的顺序保持一致。
如将上面例程稍作修改,对于HashSet:
import java.util.*; public class HashTest { @SuppressWarnings("unchecked") public static void main(String[] args){ HashSet hashSet1 = new HashSet(); //hashSet1.add(1); hashSet1.add("abc"); hashSet1.add("abc"); int[] arr = new int[]{1,2,3}; //hashSet1.add(arr); hashSet1.add(1); HashTest ht = new HashTest(); Apple apple1 = ht.new Apple(); hashSet1.add(apple1); hashSet1.add(arr); Iterator it = hashSet1.iterator(); System.out.println(hashSet1.size()); while(it.hasNext()){ Object ob = it.next(); if(ob instanceof Integer) System.out.println("Integer:" + ob); if(ob instanceof String) System.out.println("String:" + ob); if(ob instanceof Apple) System.out.println("Apple:" + ob); if(ob instanceof int[]){ System.out.print("int[]:"); System.out.println(Arrays.toString(arr)); } } } public class Apple{ static final int id = 1; @Override public String toString() { return "Apple " + id; } } }
输出为:
4
Integer:1
String:abc
Apple:Apple 1
int[]:[1, 2, 3]
可见迭代顺序与插入顺序不一致
然后仅仅将
HashSet hashSet1 = new HashSet(); 改为:LinkedHashSet hashSet1 = new LinkedHashSet();
输出结果变为:
4
String:abc
Integer:1
Apple:Apple 1
int[]:[1, 2, 3]
与插入顺序一致!
- SortedSet TreeSet
SortedSet:
1) 顾名思义就是有序的Set,但是它的有序和LinkedHashSet不一样,LinkedHashSet维护的是插入时的顺序,而SortedSet维护的是元素之间大小关系的顺序(比如升序、降序等,是根据大小关系来维护顺序的);
2) 这种维护是时刻维护的(就跟堆维护堆序一样),每次插入元素的时候就会根据其大小放入合适的位置,删除一个元素后也会调整剩余元素的位置使之符合升序/降序状态;
3) SortedSet的实现类不多,基本只会用TreeSet这个实现类,之所以叫TreeSet,是因为它使用红黑树实现的,因此内部是一个树的结构
TreeSet:
实现Set 接口,该接口由TreeMap 实例支持。此类保证排序后的 set 按照升序排列元素, 根据使用的构造方法不同,可能会按照元素的自然顺序 进行排序(参见 Comparable),或按照在创建 set 时所提供的比较器进行排序。四种构造方法:
TreeSet()
Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
|
TreeSet(Collection<? extends E> c)
Constructs a new tree set containing the elements in the specified collection, sorted according to the
natural ordering of its elements.
|
TreeSet(Comparator<? super E> comparator)
Constructs a new, empty tree set, sorted according to the specified comparator.
|
TreeSet(SortedSet<E> s)
Constructs a new tree set containing the same elements and using the same ordering as the specified sorted set.
|
注意1:允许 null 元素.
注意2:实现不同步的,不是线程安全的。
注意3:TreeSet 实例将使用其 compareTo(或 compare)方法执行所有的键比较,
认为两个对象的键相等就表示它们两个对象是相等的。它违背了 Set 接口的常规协定。
注意4:此类的iterator方法返回的迭代器是快速失败 的:在创建迭代器之后,如果对集合进行修改,
除非通过迭代器自身的 remove 方法,否则在任何时间以任何方式对其进行修改,
Iterator 都将抛出 ConcurrentModificationException
注意5:iterator()返回的迭代器,里面的元素是以升序排序的.
注意6:当试图添加一个重复元素到TreeSet时,新元素并不会把旧元素替换掉,
而只是新元素不会添加到TreeSet(不会抛异常。)
注意7:TreeSet用了一种叫红黑树的数据结构【red-black tree data structure】来为元素排序,
例程:
import java.util.Comparator; import java.util.Random; import java.util.TreeSet; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; public class Test2 { /** * @param args */ public static void main(String[] args) { PeopleComparator comparator=new PeopleComparator(); TreeSet<People> set=new TreeSet(comparator); set.add(new People("robin",1,21)); set.add(new People("hb",2,20)); set.add(new People("harry",9,30)); set.add(null); People p4=new People("robin",4,25); set.add(p4); set.add(new People("yp",5,28)); set.add(new People("yp2",8,28)); for(People p:set) System.out.println(p); } } class People{ String name; int id; int age; public People(String name,int id){ this(name,id,0); } public People(String name,int id,int age){ this.name=name; this.id=id; this.age=age; } public String toString(){ return id+name+age; } } class PeopleComparator implements Comparator<People> { @Override public int compare(People p0, People p1) { if(p0==p1) return 0; if(p0!=null&&p1==null) return 1; else if(p0==null&&p1!=null) return -1; if (p0.id>p1.id) return 1; else if (p0.id<p1.id) return -1; else return 0; } }
输出结果:
null
1robin21
2hb20
4robin25
5yp28
8yp228
9harry30