一个项目中如果只是使用数组操作已知个数的对象并清楚知道每个对象的生命周期,那么这将是一个非常简单的程序。面对现在庞大且复杂的业务逻辑,用数组持有对象是远远不够的,于是Java提供了容器类库,以达到管理可变对象个数的要求。
一、Java容器类库
- 用途——保存对象
- Arrays.asList()方法接受一个数组或一个用逗号分割的元素列表(及接收一个可变参数),并将其转换为一个List对象;
- Collections.addAll()方法接受一个Collection对象,以及一个数组或是用一个逗号分割的列表(及接收一个可变参数),将元素添加到Collection中;
- Collection本身有一个构造器可以接收另一个Collection用以初始化自身;
- Collection.addAll()只能接收另一个Collection,所以用起来并没有Collections.addAll()灵活,所以优先选用后者。
看一个例子:
import java.util.*; public class Box{ //创建一个接收Collention的方法 public static Collection setCollection(Collection con){ con.add("one"); con.add("two"); con.add("three"); con.add("three"); con.add("two"); return con; } //返回一个接收Map的方法 public static Map setMap(Map map){ map.put("one","one"); map.put("two","two"); map.put("three","three"); map.put("three","three"); return map; } public static void main(String[] args){ System.out.println(setCollection(new ArrayList<String>())); System.out.println(setCollection(new LinkedList<String>())); System.out.println(setCollection(new HashSet<String>())); System.out.println(setCollection(new TreeSet<String>())); System.out.println(setCollection(new LinkedHashSet<String>())); System.out.println(setMap(new HashMap<String,String>())); System.out.println(setMap(new TreeMap<String,String>())); System.out.println(setMap(new LinkedHashMap<String,String>())); } }
编译执行:
分析这个例子我们得出的结论:
- ArrayList、LinkedList、HashSet、TreeSet、LinkedHashSet 都可以向上转型为Collection,即Collection为这些集合的接公共口。
- Map为HashMap(有最快的查找技术)、TreeMap、LinkedHashMap的公共接口。
- List集合包含ArrayList和LinkedList集合,这俩个集合都可以存储重复对象。
- Set集合包含HashSet(使用了散列函数,最快的获取元素方式)、TreeSet、LinkedHashSet ,存储不同的对象。
- TreeSet(将元素存储在红-黑树数据结构中)按照比较结果的升序保存对象。
- LinkedHashSet (同样使用了散列,同时使用链表来维护元素的插入顺序)按照被添加的顺序保存对象。
- TreeMap按照比较结果的升序保存键。
- LinkedHashSet 按照被添加的顺序保存键。
- 观察运行结果发现有俩个注,意思就是我们使用了线程不安全(后续详细解读)的集合,但是并不会影响程序的运行。
二、List集合
可以将元素维护在特定的序列中(一种可变的序列)。其在Collection的基础上添加了大量的方法,使得其可以在List的中间插入和移除元素。
具体实现了俩种List:
- ArrayList——擅长随机访问数据,在中间插入和移除元素较慢。
- LinkedList——中间插入和移除元素优于前者,擅长顺序访问,随机访问较慢
*几个常用方法:
- contains()是接口Collection中的方法,用以判断一个集合是否包含某个对象,返回一个boolean类型的值,所以在List的俩个实现类中都有此方法。
- remove(引用)——删除集合中指定引用的对象。
- indexOf(引用)——获取指定引用在集合中对应的索引值。
- subList(startIndex,endIndex)——可从大的列表中创建一个片断(开始索引到结束索引间的片断,包括startIndex和endIndex)。
- containAll()——一个集合中是否包含另一个集合(也可以说成片断),集合中元素的顺序不会影响判断结果。
- retain()——求俩个集合的交集部分(判断时内部依赖与equals)。
- removeAll()——从本集合中删除参数集合的所有元素(依赖equals)。
- set()——可以替换指定索引下的元素。
- addAll()——List重写Collection的方法,可以在指定索引下插入指定的片断。当然也可以直接在集合后边追加另一个片断。
- clear()——清除集合中的所有元素
- isEmpty()——返回一个boolean类型值,判断集合是否为空。
- toArray()——可将集合转换成一个数组,传递指定类型的集合,会生成指定类型的数组。
*LinkedList集合:
其中含有使其用作栈、队列或双端队列的方法。
getFirst()\element()——俩个方法完全一样,都返回列表的第一个元素,并不移除它,如果List为空,则抛出NoSuchElement-Exception。
peek()——都返回列表的第一个元素,并不移除它,如果List为空返回null。
removeFirst()\remove()——俩个方法相同,它们移除并返回列表的头,而在列表为空时抛出NoSuchElementException异常。
poll()——与上边俩个稍有差异,只是在列表为空时返回null。
removeLast()——移除并返回列表中最后一个元素。
addFirst()\add()\addLast()——他们都将元素插入到列表的尾(端)部。
——stack(栈):
称为后进先出(LIFO)的容器,也被称为叠加栈。LinkedList具有能够直接实现栈的所有功能的方法,因此可以直接将LinkedList作为栈使用。
public class Stack<T>{ private LinkedList<T> stack=new LinkedList<T>(); public void push(T t){ stack.addFirst(t); } public T peek(){ return stack.getFirst(); } public T pop(){ return stack.removeFirst(); } public boolean empty(){ return stack.isEmpty(); } public String toString(){ return stack.toString(); } }虽然在Java的util类库中创建了Stack类,但是在实际开发中更提倡使用上述使用LinkedList创建的栈,需要注意的一点是在创建Stack类时最好只调用栈需要的方法而不要将整个LinkedList(其中含有大量其他方法)继承下来。
三、Set集合
不保存重复的元素,因为很容易询问某个对象是否在某个Set中,所以查找是Set集合非常重要的操作,HashSet专门对快速查找进行了优化。Set与Collection有完全一样的接口,没有任何额外的功能,只是行为有所不同(此为继承与多态思想的典型应用——表现不同行为)。
import java.util.*; public class Box{ public static void main(String[] args){ Set<String> t_box=new TreeSet<String>(); //向Set集合中添加数据 Collections.addAll(t_box,"B,A,C,E,D,F".split(",")); Set<String> h_box=new HashSet<String>(); Collections.addAll(h_box,"E,D,F".split(",")); System.out.println(t_box); System.out.println(h_box); System.out.println("contains:"+t_box.contains("A")); System.out.println("containsAll:"+t_box.containsAll(h_box)); h_box.removeAll(t_box); System.out.println(h_box); System.out.println(t_box); System.out.println("isEmpty:"+h_box.isEmpty()); } }
运行结果:
使用contains()和containsAll()方法来测试Set的归属性。
未完待续。。。。。。