背景
所有集合类都位于java.util包下。集合中只能保存对象(保存对象的引用变量)。当我们把一个对象放入集合中后,系统会把所有集合元素都当成Object类的实例进行处理。
Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些接口或实现类。
Set和List接口是Collection接口派生的两个子接口,Queue是Java提供的队列实现,类似于List。
Map实现类用于保存具有映射关系的数据(key-value)。
Set、List和Map可以看做集合的三大类。
- List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
- Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是不能集合里元素不允许重复的原因)。
- Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。
接口 |
实现 |
历史集合类 |
Set |
HashSet |
|
|
TreeSet |
|
List |
ArrayList |
Vector |
|
LinkedList |
Stack |
Map |
HashMap |
Hashtable |
|
TreeMap |
Properties |
Collection
Collection接口支持如添加和除去等基本操作。设法除去一个元素时,如果这个元素存在,除去的仅仅是集合中此元素的一个实例。
- boolean add(Object element)
- boolean remove(Object element)
- int size()
- boolean isEmpty()
- boolean contains(Object element)
- Iterator iterator()
- boolean containsAll(Collection collection)
- boolean addAll(Collection collection)
- void clear()
- void removeAll(Collection collection)
- void retainAll(Collection collection)
containsAll() 方法允许您查找当前集合是否包含了另一个集合的所有元素,即另一个集合是否是当前集合的子集。其余方法是可选的,因为特定的集合可能不支持集合更改。 addAll() 方法确保另一个集合中的所有元素都被添加到当前的集合中,通常称为并。 clear() 方法从当前集合中除去所有元素。 removeAll() 方法类似于 clear() ,但只除去了元素的一个子集。 retainAll() 方法类似于 removeAll() 方法,不过可能感到它所做的与前面正好相反:它从当前集合中除去不属于另一个集合的元素,即交。
import java.util.*; public class CollectionToArray { public static void main(String[] args) { Collection collection1=new ArrayList();//创建一个集合对象 collection1.add("000");//添加对象到Collection集合中 collection1.add("111"); collection1.add("222"); System.out.println("集合collection1的大小:"+collection1.size()); System.out.println("集合collection1的内容:"+collection1); collection1.remove("000");//从集合collection1中移除掉 "000" 这个对象 System.out.println("集合collection1移除 000 后的内容:"+collection1); System.out.println("集合collection1中是否包含000 :"+collection1.contains("000")); System.out.println("集合collection1中是否包含111 :"+collection1.contains("111")); Collection collection2=new ArrayList(); collection2.addAll(collection1);//将collection1 集合中的元素全部都加到collection2中 System.out.println("集合collection2的内容:"+collection2); collection2.clear();//清空集合 collection2 中的元素 System.out.println("集合collection2是否为空 :"+collection2.isEmpty()); //将集合collection1转化为数组 Object s[]= collection1.toArray(); for(int i=0;i<s.length;i++){ System.out.println(s[i]); } } }
运行结果为: 集合collection1的大小:3 集合collection1的内容:[000, 111, 222] 集合collection1移除 000 后的内容:[111, 222] 集合collection1中是否包含000 :false 集合collection1中是否包含111 :true 集合collection2的内容:[111, 222] 集合collection2是否为空 :true 111 222
Iterator
Collection 接口的 iterator() 方法返回一个 Iterator。
Collection books = new HashSet(); books.add("Java jichu"); books.add("Java web"); Iterator it = books.iterator(); while (it.hasNext()) { String book = (String) it.next(); System.out.println(book); if(book.equals("Java web")) { books.remove(book); } } Iterator it2 = books.iterator(); while (it2.hasNext()) { String book = (String) it2.next(); System.out.println(book); }
运行结果:
Java jichu
Java web
Java jichu
1) 使用方法 iterator() 要求容器返回一个Iterator .第一次调用Iterator 的next() 方法时,它返回集合序列的第一个元素。
2)使用next() 获得集合序列的中的下一个元素。
3)使用hasNext()检查序列中是否元素。
4) 使用remove()将迭代器新返回的元素删除
Set
Set最大的特性就是不允许在其中存放的元素是重复的。
- public int size() :返回set中元素的数目,如果set包含的元素数大于Integer.MAX_VALUE,返回Integer.MAX_VALUE
- public boolean isEmpty() :如果set中不含元素,返回true
- public boolean contains(Object o) :如果set包含指定元素,返回true
- public Iterator iterator():返回set中元素的迭代器
- public Object[] toArray() :返回包含set中所有元素的数组
- public Object[] toArray(Object[] a) :返回包含set中所有元素的数组,返回数组的运行时类型是指定数组的运行时类型
- public boolean add(Object o) :如果set中不存在指定元素,则向set加入
- public boolean remove(Object o) :如果set中存在指定元素,则从set中删除
- public boolean removeAll(Collection c) :如果set包含指定集合,则从set中删除指定集合的所有元素
- public boolean containsAll(Collection c) :如果set包含指定集合的所有元素,返回true。如果指定集合也是一个set,只有是当前set的子集时,方法返回true
- public boolean addAll(Collection c) :如果set中中不存在指定集合的元素,则向set中加入所有元素
- public boolean retainAll(Collection c) :只保留set中所含的指定集合的元素(可选操作)。换言之,从set中删除所有指定集合不包含的元素。 如果指定集合也是一个set,那么该操作修改set的效果是使它的值为两个set的交集
- public boolean removeAll(Collection c) :如果set包含指定集合,则从set中删除指定集合的所有元素
- public void clear() :从set中删除所有元素
Set set1 = new HashSet(); if(set1.add("a")) { System.out.println("OK"); } if (set1.add("a")) { System.out.println("OK2"); } else { System.out.println("BAD2"); } set1.add("000"); set1.add("111"); set1.add("222"); System.out.println("集合set1的内容:"+set1); System.out.println("集合set1的大小:"+set1.size()); set1.remove("000"); System.out.println("集合set1的内容:"+set1); System.out.println("集合set1中是否包含000 :"+set1.contains("000")); System.out.println("集合set1中是否包含111 :"+set1.contains("111")); Set set2=new HashSet(); set2.add("111"); set2.addAll(set1);//将set1 集合中的元素全部都加到set2中 System.out.println("集合set2的内容:"+set2); Iterator iterator = set1.iterator();//得到一个迭代器 while (iterator.hasNext()) {//遍历 String element =(String) iterator.next(); System.out.println("iterator = " + element); } //将集合set1转化为数组 Object s[]= set1.toArray(); for(int i=0;i<s.length;i++){ System.out.println(s[i]); }
运行结果: OK BAD2 集合set1的内容:[222, 111, a, 000] 集合set1的大小:4 集合set1的内容:[222, 111, a] 集合set1中是否包含000 :false 集合set1中是否包含111 :true 集合set2的内容:[222, a, 111] iterator = 222 iterator = 111 iterator = a 222 111 a
HashSet、LinkedHashSet、TreeSet
Set set1 = new HashSet(); Set set2 = new LinkedHashSet(); for(int i =0 ; i<5 ;i++) { int s = (int)(Math.random()*100); set1.add(new Integer(s)); set2.add(new Integer(s)); System.out.println("第 "+i+" 次随机数产生为:"+s); } System.out.println("未排序前HashSet:"+set1); System.out.println("未排序前LinkedHashSet:"+set2); //使用TreeSet来对另外的Set进行重构和排序 Set sortedSet = new TreeSet(set1); System.out.println("排序后 TreeSet :"+sortedSet);
运行结果: 第 0 次随机数产生为:85 第 1 次随机数产生为:41 第 2 次随机数产生为:81 第 3 次随机数产生为:49 第 4 次随机数产生为:99 未排序前HashSet:[85, 49, 81, 99, 41] 未排序前LinkedHashSet:[85, 41, 81, 49, 99] 排序后 TreeSet :[41, 49, 81, 85, 99]
List
当我们不知道存储的数据有多少的情况,我们就可以使用List 来完成存储数据的工作。例如前面提到的一种场景。我们想要在保存一个应用系统当前的在线用户的信息。我们就可以使用一个List来存储。因为List的最大的特点就是能够自动的根据插入的数据量来动态改变容器的大小。在 List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。
- void add(int index, Object element) :添加对象element到位置index上
- boolean addAll(int index, Collection collection) :在index位置后添加容器collection中所有的元素
- Object get(int index) :取出下标为index的位置的元素
- int indexOf(Object element) :查找对象element 在List中第一次出现的位置
- int lastIndexOf(Object element) :查找对象element 在List中最后出现的位置
- Object remove(int index) :删除index位置上的元素
- Object set(int index, Object element) :将index位置上的对象替换为element 并返回老的元素。
LinkedList queue = new LinkedList(); queue.addFirst("Bernadine"); queue.addFirst("Elizabeth"); queue.addFirst("Gene"); queue.addFirst("Elizabeth"); queue.addFirst("Clara"); System.out.println(queue); queue.removeLast(); queue.removeLast(); System.out.println(queue);
运行结果:
[Clara, Elizabeth, Gene, Elizabeth, Bernadine]
[Clara, Elizabeth, Gene]
Stack<String> v = new Stack<String>(); v.push("111"); v.push("222"); v.push("333"); System.out.println(v); System.out.println(v.peek()); System.out.println(v); System.out.println(v.pop()); System.out.println(v);
运行结果: [111, 222, 333] 333 [111, 222, 333] 333 [111, 222]
List list = new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); System.out.println("下标0开始:"+list.listIterator(0).next());//next() System.out.println("下标1开始:"+list.listIterator(1).next()); System.out.println("子List 1-3:"+list.subList(1,3));//子列表 ListIterator it = list.listIterator();//默认从下标0开始 //隐式光标属性add操作 ,插入到当前的下标的前面 it.add("sss"); while(it.hasNext()){ System.out.println("next Index="+it.nextIndex()+",Object="+it.next()); } //set属性 ListIterator it1 = list.listIterator(); it1.next(); it1.set("ooo"); ListIterator it2 = list.listIterator(list.size());//下标 while(it2.hasPrevious()){ System.out.println("previous Index="+it2.previousIndex()+",Object="+it2.previous()); }
运行结果: 下标0开始:aaa 下标1开始:bbb 子List 1-3:[bbb, ccc] next Index=1,Object=aaa next Index=2,Object=bbb next Index=3,Object=ccc next Index=4,Object=ddd previous Index=4,Object=ddd previous Index=3,Object=ccc previous Index=2,Object=bbb previous Index=1,Object=aaa previous Index=0,Object=ooo
ListIterator
接口继承 Iterator
接口以支持添加或更改底层集合中的元素,还支持双向访问。
Map
数学中的映射关系在Java中就是通过Map来实现的。它表示,里面存储的元素是一个对(pair),我们通过一个对象,可以在这个映射关系中找到另外一个和这个对象相关的东西。
-
Object put(Object key,Object value)
:用来存放一个键
-
值对
Map
中
-
Object remove(Object key)
:根据
key(
键
)
,移除一个键
-
值对,并将值返回
-
void putAll(Map mapping)
:将另外一个
Map
中的元素存入当前的
Map
中
-
void clear()
:清空当前
Map
中的元素
-
Object get(Object key)
:根据
key(
键
)
取得对应的值
-
boolean containsKey(Object key)
:判断
Map
中是否存在某键(
key
)
-
boolean containsValue(Object value):
判断
Map
中是否存在某值
(value)
-
int size():
返回
Map
中
-
boolean isEmpty()
:判断当前
Map
是否为空
-
public Set keySet()
:返回所有的键(
key
),并使用
Set
容器存放
-
public Collection values()
:返回所有的值(
Value
),并使用
Collection
存放
-
public Set entrySet()
:
返回一个实现 Map.Entry 接口的元素 Set
HashMap<String, String> hm = new HashMap<String, String>(); //试图将2个key为null的key-value对放入HashMap中 hm.put(null , null); hm.put(null , null); //将一个value为null的key-value对放入HashMap中 hm.put("a" , null); hm.put("a" , "b"); //输出Map对象 System.out.println(hm);
运行结果: {null=null, a=b}
HashMap若遇到重复的key,覆盖掉以前的
Map<String, String> map1 = new HashMap<String, String>(); Map<String, String> map2 = new HashMap<String, String>(); map1.put("1","aaa1"); map1.put("2","bbb2"); map2.put("10","aaaa10"); map2.put("11","bbbb11"); //根据键 "1" 取得值:"aaa1" System.out.println("map1.get(\"1\")="+map1.get("1")); // 根据键 "1" 移除键值对"1"-"aaa1" System.out.println("map1.remove(\"1\")="+map1.remove("1")); System.out.println("map1.get(\"1\")="+map1.get("1")); map1.putAll(map2);//将map2全部元素放入map1中 map2.clear();//清空map2 System.out.println("map1 IsEmpty?="+map1.isEmpty()); System.out.println("map2 IsEmpty?="+map2.isEmpty()); System.out.println("map1 中的键值对的个数size = "+map1.size()); System.out.println("KeySet="+map1.keySet());//set System.out.println("values="+map1.values());//Collection System.out.println("entrySet="+map1.entrySet()); System.out.println("map1 是否包含键:11 = "+map1.containsKey("11")); System.out.println("map1 是否包含值:aaa1 = "+map1.containsValue("aaa1"));
运行结果: map1.get("1")=aaa1 map1.remove("1")=aaa1 map1.get("1")=null map1 IsEmpty?=false map2 IsEmpty?=true map1 中的键值对的个数size = 3 KeySet=[2, 10, 11] values=[bbb2, aaaa10, bbbb11] entrySet=[2=bbb2, 10=aaaa10, 11=bbbb11] map1 是否包含键:11 = true map1 是否包含值:aaa1 = false
Map<Integer, String> map1 = new HashMap<Integer, String>(); Map<Integer, String> map2 = new LinkedHashMap<Integer, String>(); for(int i=0;i<10;i++){ int s=(int)(Math.random()*100);//产生一个随机数,并将其放入Map中 map1.put(new Integer(s),"第 "+i+" 个放入的元素:"+s+"\n"); map2.put(new Integer(s),"第 "+i+" 个放入的元素:"+s+"\n"); } System.out.println("未排序前HashMap:"+map1); System.out.println("未排序前LinkedHashMap:"+map2); //使用TreeMap来对另外的Map进行重构和排序 Map<Integer, String> sortedMap = new TreeMap<Integer, String>(map1); System.out.println("排序后:"+sortedMap); System.out.println("排序后:"+new TreeMap<Integer, String>(map2));
运行结果: 未排序前HashMap:{68=第 3 个放入的元素:68 , 32=第 5 个放入的元素:32 , 71=第 7 个放入的元素:71 , 53=第 9 个放入的元素:53 , 37=第 8 个放入的元素:37 , 42=第 4 个放入的元素:42 , 24=第 2 个放入的元素:24 , 63=第 6 个放入的元素:63 , 29=第 0 个放入的元素:29 , 88=第 1 个放入的元素:88 } 未排序前LinkedHashMap:{29=第 0 个放入的元素:29 , 88=第 1 个放入的元素:88 , 24=第 2 个放入的元素:24 , 68=第 3 个放入的元素:68 , 42=第 4 个放入的元素:42 , 32=第 5 个放入的元素:32 , 63=第 6 个放入的元素:63 , 71=第 7 个放入的元素:71 , 37=第 8 个放入的元素:37 , 53=第 9 个放入的元素:53 } 排序后:{24=第 2 个放入的元素:24 , 29=第 0 个放入的元素:29 , 32=第 5 个放入的元素:32 , 37=第 8 个放入的元素:37 , 42=第 4 个放入的元素:42 , 53=第 9 个放入的元素:53 , 63=第 6 个放入的元素:63 , 68=第 3 个放入的元素:68 , 71=第 7 个放入的元素:71 , 88=第 1 个放入的元素:88 } 排序后:{24=第 2 个放入的元素:24 , 29=第 0 个放入的元素:29 , 32=第 5 个放入的元素:32 , 37=第 8 个放入的元素:37 , 42=第 4 个放入的元素:42 , 53=第 9 个放入的元素:53 , 63=第 6 个放入的元素:63 , 68=第 3 个放入的元素:68 , 71=第 7 个放入的元素:71 , 88=第 1 个放入的元素:88 }
从运行结果,我们可以看出,HashMap的存入顺序和输出顺序无关。而LinkedHashMap 则保留了键值对的存入顺序。TreeMap则是对Map中的元素进行排序。在实际的使用中我们也经常这样做:使用HashMap或者LinkedHashMap 来存放元素,当所有的元素都存放完成后,如果使用则是需要一个经过排序的Map的话,我们再使用TreeMap来重构原来的Map对象。这样做的好处是:因为HashMap和LinkedHashMap 存储数据的速度比直接使用TreeMap 要快,存取效率要高。当完成了所有的元素的存放后,我们再对整个的Map中的元素进行排序。这样可以提高整个程序的运行的效率,缩短执行时间。