集合类的要点总结
1. Collections.addAll VS Collection.addAll
Collection.addAll只能添加一个Collection类型的对象,而Collections.addAll支持可变参数列表。
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
list1.add("c");
List<String> list2 = new ArrayList<String>();
list2.addAll(list1);//list2 为[a,b,c]
Collections.addAll(list2, "e","f");
Collections.addAll(list2, list1.toArray(new String[]{}));//list2为[a,b,c,e,f,a,b,c]
for(int i=0; i<list2.size(); i++){
System.out.println(list2.get(i));
}
}
2. Arrays.asList
这个方法接收一个可变参数,然后返回一个List类型的变量,但请注意,由于返回的List的内部实现包含的是
Private final E[] a;这样的东西,所以返回的List对象不可以add和remove,否则就会抛出java.lang.UnsupportedOperationException这个异常。
public static void main(String[] args) {
List<String> strList = Arrays.asList("a","b","c");
strList.add("d");//抛出java.lang.UnsupportedOperationException
strList.remove(0);//抛出java.lang.UnsupportedOperationException
System.out.println(strList);
}
3. 判断一个集合类是否包含另一个集合类
利用Collection的非静态方法containsAll(Collection col)进行判定,注意这里采用的实现方法是遍历col,调用contains方法一个一个进行判定,而contains方法则利用了equals方法进行判定。
class User{
int age;
String name;
public User(int age , String name){
this.age = age;
this.name = name;
}
public boolean equals(Object object){
User user = (User)object;
return ( this.age==user.age && this.name.equals(user.name) );
}
}
public final class ContainsAllTest {
public static void main(String[] args) {
List<User> list1 = new ArrayList<User>();
list1.add(new User(1,"a"));
list1.add(new User(2,"b"));
list1.add(new User(3,"c"));
List<User> list2 = new ArrayList<User>();
list2.add(new User(1,"a"));
System.out.println(list1.containsAll(list2));//true
}
}
4. Comparable VS Comparator(两大比较器)
若想让两个对象具有可比性,有两种方式,一种是让该类直接实现Comparable接口,然后实现其compareTo方法,另一种方法是提供一个Comparator(比较器),比如在Collections.sort中可以自己提供一个比较器,从而可以适用各种各样的比较。采用Comparable接口的方式只能实现一种比较方法,而采用Comparator则可以实现多种比较(每次比较提供不同的比较器),这其实便是设计模式中的策略模式。
一个使用Comparable的例子
public final class CompareTest {
private static class User implements Comparable{
String name;
int age;
private User(String name , int age){
this.name = name;
this.age = age;
}
//先比较名字,大者则大,若名字相等再比较年龄
public int compareTo(Object obj){
User user = (User)obj;
int result = this.name.compareTo(user.name);
if(result != 0){
return result;
}
return this.age>user.age?1:(this.age<user.age?-1:0);
}
public String toString(){
return name + ":" + age ;
}
}
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User("zhangsan",20));
users.add(new User("lisi",18));
users.add(new User("wangwu",22));
Collections.sort(users);
for(User user : users){
System.out.println(user);
}
}
}
//输出结果为
//lisi:18
//wangwu:22
//zhangsan:20
把该例子换成使用Comparator
public final class CompareTest {
private static class User{
String name;
int age;
private User(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return name + ":" + age ;
}
}
private static class ComparatorImpl implements Comparator{
@Override
public int compare(Object o1, Object o2) {
User user1 = (User)o1;
User user2 = (User)o2;
int result = user1.name.compareTo(user2.name);
if(result != 0){
return result;
}
return user1.age>user2.age?1:(user1.age<user2.age?-1:0);
}
}
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User("zhangsan",20));
users.add(new User("lisi",18));
users.add(new User("wangwu",22));
Collections.sort(users , new ComparatorImpl());
for(User user : users){
System.out.println(user);
}
}
}
//输出结果为
//lisi:18
//wangwu:22
//zhangsan:20
5. 求两个Collection的交集
利用Collection的retainAll方法
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
List<String> list2 = new ArrayList<String>();
list2.add("b");
list2.add("c");
list1.retainAll(list2);
System.out.println(list1);
}
//输出结果为
//[b]
6. Iterator的三个基本方法
Iterator有三个方法,hasNext,next,remove,其中,remove删除前一个next返回的那个元素。
public static void main(String[] args) {
List<String> strs = new ArrayList<String>();
strs.add("a");
strs.add("b");
strs.add("c");
Iterator<String> it = strs.iterator();
while(it.hasNext()){
System.out.println(it.next());
it.remove();//删除上面打出的元素
}
System.out.println("size = " + strs.size());
}
//输出结果为:
a
b
cvs
size = 0
7. 专门服务于List的ListIterator
Iterator只有三个基本的方法,支持向前的迭代访问,而专门针对于List,可以返回一个ListIterator的迭代器,它支持前后双向的迭代,功能较强大。基本方法有
hasNext,next,hasPrevious,previous,nextIndex,previousIndex,remove,set,add.
8. Stack
Java.util包中有一个叫Stack的类,它直接继承自Vector,我们知道,Vector 是同步的,所以此种Stack自然也是同步的。由于Vector中有许多不适用于Stack的方法,所以一般不使用此Stack。当要用到Stack的时候,一般情况下我们可以利用LinkedList方便的实现自己的Stack.
如下是一个简单的自定义Stack的实现
public final class StaclTest {
private static class Stack<T>{
LinkedList<T> list = new LinkedList<T>();
public boolean empty(){
return list.isEmpty();
}
public T peek(){
return list.getFirst();
}
public T pop(){
return list.removeFirst();
}
public void push(T target){
list.addFirst(target);
}
public int size(){
return list.size();
}
}
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
stack.push("a");
stack.push("b");
stack.push("c");
printStack(stack);
System.out.println("size = " + stack.size());
}
public static <T> void printStack(Stack<T> stack){
int size = stack.size();
for(int i=0; i<size; i++){
System.out.println(stack.pop());
}
}
}
//输出结果如下
c
b
a
size = 0
9. 认识map中的几个主要方法
Map是非常重要的一种数据结构,有几个比较重要的方法,如
containsKey,containsValue,keySet,values,注意keySet方法。此方法返回一个Set类型的集合,但是这个Set里边装的是Map.Entry这种类型的引用,何为Map.Entry呢?其实,一个Map.Entry里边有一个key和value,所以一个Map.Entry就是对一对键值对的包装,所以Map.Entry有getKey和getValue方法也就非常自然了。看一个简单的例子
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
Set<Map.Entry<String, String>> keySets = map.entrySet();
map.put("1", "a");
map.put("2", "a");
System.out.println(keySets);
Collection<String> values = map.values();
System.out.println(values);
}
// 输出结果为
[2=a, 1=a]
[a, a]
10. 了解PriorityQueue。
我想从它的名字就可以猜出它是一个有优先级作为指导的队列了,就像我们系统中有很多个进程一样,每个进程都有不同的优先级,这是在j2se1.5中才新引入的。那么如何设置其优先级呢?其实问题归结到底还是回归到了Comparator(比较器)。
PriorityQueue有如下构造方法
PriorityQueue(int initialCapacity,
Comparator<? super
E> comparator)
第一个参数为初始化容量大小,第二个为一个比较器,这样,你完全可以提供自己的比较器的实现类来指导PriorityQueue如何对元素按优先级进行访问。注意,队列只能在一端进行访问,在另一端进行插入。PriorityQueue能够保证每次获取的数据都是按你所愿的。但是如果你一下子打印出整个队列的话,那么它并不会整个都是排好序的,如下
public final class PriorityQueueTest {
private static class ComparatorImpl implements Comparator{
public int compare(Object obj1 , Object obj2){
int result = ((Integer)obj1).compareTo((Integer)obj2);
return result>0?-1:(result<0?1:0);
}
}
public static void main(String[] args) {
Queue<Integer> priorityQueue = new PriorityQueue<Integer>(10 , new ComparatorImpl());
priorityQueue.add(10);
priorityQueue.add(20);
priorityQueue.add(8);
priorityQueue.add(11);
while(!priorityQueue.isEmpty()){
System.out.println(priorityQueue);
System.out.println("poll():" + priorityQueue.poll());
}
}
}
//运行结果如下
[20, 11, 8, 10]
poll():20
[11, 10, 8]
poll():11
[10, 8]
poll():10
[8]
poll():8
可以看出,直接打出PriorityQueue中的所有元素时并不是都排好序了,但是第一个元素绝对是正确的排序的。这跟它的具体实现有关,具体可以查看源代码。(底层采用树型结构存储)
11. Iterable接口的妙用
Jdk1.5中新增了加强的for语句,也就是foreach statement,它跟Iterable有何关系呢?其实,当一个类实现了Iterable接口后,便可用于foreach statement。看如下例子
public final class IterableTest {
protected User[] users = new User[4];
public User[] getUsers(){
return this.users;
}
private static class User{
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
private class MyCollection<T> implements Iterable<T>{
private int index = 0;
@Override
public Iterator<T> iterator() {
return new Iterator<T>(){
@Override
public boolean hasNext() {
return index < users.length;
}
@Override
public T next() {
if(hasNext()){
return (T)users[index++];
}else{
return null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
public static void main(String[] args) {
IterableTest myIterable = new IterableTest();
User[] users = myIterable.getUsers();
users[0] = new User("a");
users[1] = new User("b");
users[2] = new User("c");
users[3] = new User("d");
MyCollection<User> myColl = myIterable.new MyCollection<User>();
for(User user : myColl){
System.out.println(user.getName());
}
}
}
//输出结果如下
a
b
c
d
注意如下代码
MyCollection<User> myColl = myIterable.new MyCollection<User>();
这是非静态内部类的创建方式。
当执行时,jvm会自动去调用myColl 中的iterator方法,然后利用返回的Iterator进行迭代。