集合的存在是为了解决什么问题?
大概就是在编程的时候可以在任意时刻和任意位置创建任意数量的对象。
数组是保存一组对象的有效方式,但数组有固定的尺寸大小,且在一般情况下,写程序时不知道将需要多少对象,或者是否需要更复杂的方法来存储对象,这一点数组就存在诸多限制。
java.util 库提供了一套相当完整的 集合类 (collection classes)来解决此问题。其中基本类型有 List、Set、Queue 和 Map。这些类型也被成为容器类(container classes)。集合提供完善的办法保存对象,可使用这些工具解决大量问题。
Java集合类能自动调整自身大小,可将任意数量对象放置集合中,不用关心集合应该要设置多大。
基本概念
Java集合类库采用“持有对象”思想,将其分为两个不同的概念,表示为类库的基本接口:
- 集合(Collection):独立元素的序列,服从一条或多条规则。List必须以插入顺序保存元素,Set不能包含重复元素,Queue按照排队规则确定对象产生顺序,一般与插入顺序相同。
-
映射(Map):成对的“键值对”对象,允许使用键来查找值。map允许使用一个对象来查找另一个对象,也被称为 关联数组 或者是 字典 ,基本思想都是由一个对象引出另外一个对象。Map是强大的编程工具。
Collection接口概括了 序列 的概念——一种存放一组对象的方式,以下给出一个实例,用Integer对象填充一个Collection(此处用ArrayList表示),然后打印集合中的元素:
import java.util.*;
public class SimpleCollection {
public static void main(String[] args) {
Collection<Integer> chs = new ArrayList<>();
for (int i = 0; i < 5; i++) {
chs.add(i);
}
for (Integer i: chs) {
System.out.print(i+" ");
}
}
}
结果:
如果我们想要在一个Collection中添加一组元素如何实现?首选是构建一个一个不包含元素的Collection,然后调用Collections.addAll(),这种方法运行较快。当然,Collection的构造器可以接受另一个Collection,用它来进行自身初始化,这里可以使用Arrays.asList()来为构造器产生输入。
Collection.addAll() 方法只能接受另一个Collection作为参数,没有上面两个方法灵活,上面两个方法都是使用可变参数列表。
也可直接使用Arrays.asList()的输出作为一个List,但这里底层实现仍然是数组,无法改变大小,如果尝试使用add()或remove()尝试修改数组大小,在运行时会抛错。
以下给出上述方法的具体实现例子:
import java.util.*;
public class AddingGroups {
public static void main(String[] args) {
Collection<Integer> chs = new ArrayList<>();
Integer[] addInt = {1,2,3};
chs.addAll(Arrays.asList(addInt));
System.out.println(chs);
Collections.addAll(chs,4,5,6);
System.out.println(chs);
Collections.addAll(chs,addInt);
System.out.println(chs);
List<Integer> list = Arrays.asList(7,8,9);
System.out.println(list);
list.set(1,100);
System.out.println(list);
}
}
结果:
上面这个例子可以看到我在打印集合的时候直接输入名字就可打印,这里默认的打印行为采用的是集合提供的toString()方法,Collection打印出的内容用方括号括住,每个元素用逗号分隔。如果我们打印Map会是什么效果呢?用一个例子来解释:
import java.util.*;
public class PrintMap {
static Map chs(Map<String,String> map){
map.put("cat","Kitty");
map.put("mouse","Tom");
map.put("dog","Spot");
map.put("dog","Bobe");
return map;
}
public static void main(String[] args) {
System.out.println(chs(new HashMap<>()));
System.out.println(chs(new TreeMap<>()));
System.out.println(chs(new LinkedHashMap<>()));
}
}
结果:
可以看到打印出来的Map由大括号括住,每个键和值用等号连接,键在左边,值在右边,键值对之间用逗号分隔。
Map.put(key,value)可用于添加一个值并将其与一个键相关联。Map.get(key)生成与该键相关联的值。
注意到本例使用了Map的三种风格:HashMap、TreeMap、LinkedHashMap。
键和值保存在HashMap中的顺序不是插入顺序,因为HashMap实现使用了非常快速的算法来控制顺序;TreeMap通过比较结果的升序来保存键;LinkedHashMap在保存HashMap查找速度的同时按键的插入顺序保存键。