基本概念
如下图:
为解决数组固定尺寸的限制,java类库提供容器类来解决这问题。其中包括List,Set,Map,Queue,也称集合类。编程时可以将任意数量的对象置于容器,不用在意容器大小。
容器类库可以划分为:
- Collection:独立的序列,元素服从一条或多条规则。其中List按照插入的顺序保持元素,Set不能有重复元素,Queue按照排队规则确定对象产生的顺序。
- Map:一组成对的键值对对象,允许用键查找,ArrayList允许用数字查找值。
向Collection添加一组元素
java.util包中的Arrays和Collections类的Arrays.asList()方法和Collections.addAll()方法可以在Collection对象中添加一组元素。
- Arrays.asList()接受一个数组或是逗号分隔的元素列表,将其妆化为List对象;
- Collections.addALl()接受一个Collection对象,以及一个数组或者逗号分隔的元素列表,将元素添加到Collection中;
- Collection.addAll()运行快,只能接受Collection对象作为参数,所以不如前两者灵活。
如下:
public class addGroups(){
public static void main(String[] args){
Conllection<Integer> conllection = new ArrayList<Integer>(Arrays.asList(1,2,3));
Integer[] moreInts = {4,5,6};
collection.addAll(Arrays.asList(moreInts));
Collections.addAlls(conllection, 7,8,9);
Collections.addAlls(conllection, moreInts);
}
}
可以直接使用Arrays.asList()的输出,将其作为List,此时,底层表示为数组,无法调整尺寸,若用add(),delete()添加或删除元素,会引发改变数组尺寸,产生错误。
List<Integer> list = Arrays.asList(10,11,12);
list.set(1,99); //可以修改元素值
list.add(13); //产生错误,尝试改变数组尺寸
List
List可以将元素维护在特定的序列中,有两种类型List:
- ArrayList:随机访问元素快速,在List中插入和移除元素比较慢
- LinkedList:通过代价较低的在List中进行插入删除,提供了优化的顺序访问,LinkedList在随机访问方面比较慢,但特性集比ArrayList更大。
具体方法操作如下例所示:
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList("red","blue","white","grey"));
//add(int index,String value)向List中添加插入元素
list.add("yellow");
out.println(list);
//contains(String value)判断List中是否包含该元素
out.println(list.contains("yellow"));
//indexOf(String value)查询元素的位置
out.println(list.indexOf("blue"));
//remove(String value)删除元素
out.println(list.remove("blue"));
out.println(list);
//subList(int index,int _index)截取片断,返回一个新的List对象
List<String> _list = list.subList(1,4);
out.println(_list);
//containAll(List object)判断一个List中是否包含另一个List中的所有值
out.println(list.containsAll(_list));
//Collections.sort(List object)对List进行排序
Collections.sort(_list);
out.println(_list);
List<String> copy_list = new ArrayList<>(list);
_list = Arrays.asList(list.get(1),list.get(3));
out.println(_list);
out.println(copy_list);
//retainAll()取交集
copy_list.retainAll(_list);
out.println(copy_list);
//removeALl()从List中移除参数List中所有元素
copy_list.removeAll(_list);
out.println(copy_list);
//set()设值,在指定索引处,替换位置上的元素
list.set(1,"green");
out.println(list);
//addAll()在List中插入新的列表
list.addAll(1,_list);
out.println(list);
//isEmpty()判断List是否为空
out.println(list.isEmpty());
//clear()清除所有元素
list.clear();
out.println(list);
//toArray()将Collection转换为一个数组,为重载方法,无参版本返回的是Object数组
Object[] array = _list.toArray();
out.println(array[0]);
}
}
Iterator
迭代器(设计模式)是一个对象,用来遍历并选择序列中的对象,通常被称为轻量级对象,创建代价小。Java的Iterator只能单向移动。
- iterator()要求容器返回一个Iterator;
- 使用next()获得序列中下一个元素;
- 使用hasNext()检查序列中是否还有元素;
- remove()将迭代器返回的元素删除;
如下示例:
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList("red","blue","white","grey"));
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
String s = iter.next();
out.println(s);
}
for(String _s : list)
out.println(_s);
iter = list.iterator();
for(int i = 0;i < 2;i++){
iter.next();
iter.remove();
}
out.println(list);
}
}
若是所创建的List能把相同的代码应用于Set,将显得很方便,代码重组显然不适合,所以我们使用迭代器。创建一个display()方法:
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void display(Iterator<String> iter){
while(iter.hasNext()){
String s = iter.next();
out.println(s);
}
}
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList("red", "blue", "white", "grey"));
LinkedList<String> L_list = new LinkedList<String>(list);
HashSet<String> H_list = new HashSet<String>(list);
TreeSet<String> T_list = new TreeSet<String>(list);
display(list.iterator());
display(L_list.iterator());
display(H_list.iterator());
display(T_list.iterator());
}
}
ListIterator
ListIterator是Iterator的子类型,用于LIst的访问。Iterator只能单向移动,但是ListIterator可以双向移动。
其中的previousIndex()和nextIndex()可以获取到当前位置的前一个和后一个元素索引,hasPrevious()判断一个元素是否存在,set()用于替换元素。
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList("red", "blue", "white", "grey"));
ListIterator<String> iter = list.listIterator();
while(iter.hasNext()){
System.out.print(iter.next()+","+iter.nextIndex()+","+iter.previousIndex()+" ");
}
System.out.println();
while(iter.hasPrevious())
out.print(iter.previous()+" ");
out.println();
iter = list.listIterator(2);
while(iter.hasNext()){
iter.next();
iter.set("girl");
}
out.println(list);
}
}
LinkedList
LinkedList随机访问比ArrayList逊色,但是元素的插入删除比ArrayList迅速的多。LinkedList添加了栈,队列,双端队列的方法。
- getFirst(),element():返回列表的头元素,而不是移除,若列表为空,则抛出NoSunchElementException;
- peek():同上,只是列表为空时,返回null;
- removeFirst(),remove():移除并返回列表的头,列表为空抛出NoSunchElementException;
- poll():同上,只是列表为空返回null;
- addFirst(),add(),addLast():将某个元素插入到列表的(端)尾部;
removeLast():移除并返回列表最后一个元素;
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
LinkedList list = new LinkedList(Arrays.asList(“red”,”blue”,”green”,”yellow”));
out.println(list);
out.println(“getFirst():”+list.getFirst());
out.println(“element():”+list.element());
out.println(“peek():”+list.peek());
out.println(“remove():”+list.remove());
out.println(“removeFirst():”+list.removeFirst());
out.println(“poll():”+list.poll());
list.addFirst(“red”);
list.addLast(“blue”);
out.println(list);
out.println(“removeLast():”+list.removeLast());
}
}[red, blue, green, yellow]
getFirst():red
element():red
peek():red
remove():red
removeFirst():blue
poll():green
[red, yellow, blue]
removeLast():blue
Stack
“栈”称为“先进后出”(LIFO)容器。有时也称作叠加栈。最后压入的元素,最后一个弹出。LinkedList可以实现Java中的栈。
使用LInkedList定义一个Stack类:
import java.util.LinkedList;
public class Stack<T>{
private LinkedList<T> Storage = new LinkedList<T>();
public void push(T v) {
storage.addFirst(v);
}
public T peek(){
return storage.getFirst();
}
public T pop(){
return storage.removeFirst();
}
public boolean empty(){
return storage.isEmpty();
}
public String toString(){
return storage.toString();
}
}
Set
Set不保存重复元素,常用作测试归属性可以很容易判断对象是否在Set中,加快了对快速查询的优化。
Set有着与Collection完全一样的接口,没有任何额外功能,只是行为不同而已。如下为Set示例:
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
Random rand = new Random(47);
//Set<Integer> set = new HashSet<Integer>();
//Set<Integer> set = new TreeSet<Integer>();
Set<Integer> set = new LinkedHashSet<Integer>();
for(int i = 0;i<1000;i++){
set.add(rand.nextInt(30));
}
out.println(set);
}
}
运行结果:
HashSet:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
TreeSet:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
LinkedHashSet
[8, 5, 13, 11, 1, 29, 28, 20, 12, 7, 18, 21, 19, 16, 0, 14, 3, 26, 25, 10, 2, 24, 4, 6, 22, 27, 17, 9, 23, 15]
由运行结果可知,HashSet和TreeSet按顺序输出,以往的HashSet使用的是散列,现在或许已经改变了元素存储方式,TreeSet存储在红黑树中,LinkedHashSet使用了散列存储,看起来更是使用了链表维护元素插入顺序。
- contains()和containsAll(Set对象)用来检查元素的归属
- remove()和removeAll(Set对象)用来删除元素
若是想要列出一个文件上所有的单词时,可以使用net.mindview.TextFile工具,并将其写入Set中。
new TextFile("Exzample.hava", "\\W+");
其中“\W+”表示正则表达式“一个或多个字母”。
Queue
队列是“先进先出”容器,容器一段放入元素,另一端取出。LinkedList支持队列的行为,实现了Queue接口,可以通过LinkedList向上转型为Queue。
Queue<String> queue = new LinkedList<String>();
其中Queue的offer()方法可以将一个元素插入到队尾,或返回false。peek()和element()在不移除的情况返回队头。poll()和remove()移除并返回队头。
Map
Map是一种将对象与对象相关联的设计,HashMap设计用来快速访问,而TreeMap保持“键”始终处于排序状态,所以没有HashMap快,LInkedHashMap保持元素插入的顺序,但也通过散列提供快速访问的能力。
Map可以将对象映射到其他对象。例如,对Random产生的数字进行计数,键位Random产生的数字,值是数字出现的次数。
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
Random rand = new Random(47);
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for(int i =0; i<1000;i++){
int r= rand.nextInt(30);
Integer num = map.get(r);
map.put(r, num==null?1:num+1);
}
out.println(map);
}
}
此外,可以通过containsKey()和containsValue()测试一个Map,判断是否包含某个键或某个值。
import java.util.*;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(0, "red");
map.put(1, "blue");
map.put(2, "yellow");
out.println(map);
out.println(map.containsKey(1));
out.println(map.containsValue("blue"));
}
}