删除元素,对于next和remove的调用是互相依赖的,如果调用remove之前没有调用next,则会跑出IllegalStateException异常。如果想要删除两个相连的元素:
it.remove();
it.remove();//error
而是应该
it.remove();
it.next();
it.remove();
怎么觉得这种接口设计好傻呢。谁干的?
如果想要实现自己的集合类,可以从Abstractxxxx系列的抽象类来扩展,这样可以少实现很多方法。比如AbstractCollection, AbstractQueue方法。
java中的迭代器和与c++中的迭代器是不同的,java中的集合本身实现了迭代器接口,而c++中则是通过
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class LearnCollection {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("zhang.san");
nameList.add("li.si");
nameList.add("wang.wu");
nameList.add("zhao.yi");
System.out.println("initial content.");
printCollection(nameList);
printViaIterator(nameList.iterator());
removeViaIterator(nameList.iterator(), "li.si");
System.out.println("");
System.out.println("after remove li.si");
printCollection(nameList);
printViaIterator(nameList.iterator());
}
/**
* remove via iterator
* @param it
* @param value
*/
static void removeViaIterator(Iterator<?> it, String value){
while(it.hasNext()){
if(it.next().toString() == value){
it.remove();
System.out.println(String.format("remove %s success.", value));
return;
}
}
System.out.println(String.format("remove %s failed.", value));
}
/**
* @param it
*/
static void printViaIterator(Iterator<?> it){
System.out.println("Print via iterator:");
while(it.hasNext())
System.out.println(String.format(" item:%s", it.next().toString()));
}
/**
* @param collection
*/
static void printCollection(Collection<?> collection){
System.out.println("collection content:");
for(Object item: collection){
System.out.println(String.format(" item:%s", item.toString()));
}
}
}
下面测试一下Collection.toArray的用法。
从下面的代码可以看出,当arrayToFill的大小不够的时候,就不会填充。
static void testToArray(){
LinkedList<String> strList = new LinkedList<String>();
strList.add("zhang.san");
strList.add("li.si");
strList.add("wang.wu");
print("filled array is not large enough.");
testToArrayHelper(strList, new String[2]);
print("filled array is large enough.");
testToArrayHelper(strList, new String[3]);
}
static void testToArrayHelper(LinkedList<String> strList, String[] filledArray){
String[] returnedArray = strList.toArray(filledArray);
printArray("filled array:", filledArray);
print("");
printArray("returned array:", returnedArray);
print("");
if(filledArray == returnedArray)
print("filled array is equal returned array.");
else
print("filled array is not equal returned array.");
}
static <T> void printArray(String title, T[] array){
print(title);
for(T item: array){
if(item != null)
print("item:" + item.toString());
else
print("item is null");
}
}
static void print(String info){
System.out.println(info);
}
输出结果如下:
filled array is not large enough.
filled array:
item is null
item is null
returned array:
item:zhang.san
item:li.si
item:wang.wu
filled array is not equal returned array.
filled array is large enough.
filled array:
item:zhang.san
item:li.si
item:wang.wu
returned array:
item:zhang.san
item:li.si
item:wang.wu
filled array is equal returned array.
13.2 具体的集合
除了以map结尾的类,其他都实现了collection接口。
关于LinkedList的 ListIterator的add和remove
static void testListIteratorAdd(){
LinkedList<String> strList = new LinkedList<String>();
strList.add("1");
strList.add("2");
strList.add("3");
print("init content:");
printCollection(strList);
ListIterator<String> it = strList.listIterator();
it.next();
it.add("1.1");
it.add("1.2");
print("after insert 2 item");
printCollection(strList);
}
输出如下:
init content:
collection content:
item:1
item:2
item:3
after insert 2 item
collection content:
item:1
item:1.1
item:1.2
item:2
item:3
测试listIterator的删除功能。
static void testListIteratorRemove(){
LinkedList<String> strList = new LinkedList<String>();
strList.add("1");
strList.add("2");
strList.add("3");
print("init content:");
printCollection(strList);
ListIterator<String> it = strList.listIterator();
it.next();
it.remove();//ok
print("after remove 1 item");
printCollection(strList);
it.remove();//error
print("after remove 2 item");
printCollection(strList);
}
输出如下,也就是说,ListIterator.remove是依赖于迭代器的状态的,每次调用remove之前,必须先调用一次next或者previous函数。
init content:
collection content:
item:1
item:2
item:3
after remove 1 item
collection content:
item:2
item:3
Exception in thread "main" java.lang.IllegalStateException
at java.util.LinkedList$ListItr.remove(LinkedList.java:923)
at me.ygc.javabasic.learnJava.LearnCollection.testListIteratorRemove(LearnCollection.java:33)
at me.ygc.javabasic.learnJava.LearnCollection.main(LearnCollection.java:15)
13.2.3 散列集
在java中,散列表用链表数组实现,每个列表被称为桶(bucket), 先用散列码找到桶,然后在桶内使用equals方法来逐个比较查找。
如果散列表太满,就要再散列。也就是创建一个新的更大的散列表,将原来的所有元素转移过去,然后丢弃原来的表。
装填因子默认值为0.75,当超过0.75的时候,就会自动进行再散列。
只有不关心集合中元素位置的时候,才会使用HashSet。
13.2.8 映射表
有两种, HashMap,无序的, TreeMap,有序的;
如果不需要排序,就选择HashMap,因为这个会稍微快一点。