给大忙人看的Java核心技术笔记(7、集合)
要点:
1、Collection接口为所有集合类提供了共同方法(映射除外,映射是通过Map接口描述的)
2、列表是一个有序集合,其中的每个元素都有一个整数索引
3、set针对高效包含测试进行过优化。Java提供了HashSet和TreeSet实现
4、对映射来说,可以选择HashMap或TreeMap实现。LinkedHashMap会记住元素插入的顺序。
5、Collection接口和Collections类提供了很多有用的算法:如设置操作,查询、排序、打乱原先顺序等
6、视图通过使用标准集合接口提供了对存储在其他地方的数据的访问
1、简介
ArrayList和LinkedList,一个是链表,一个是线性表。
List接口提供了访问列表中第n个元素的方法,尽管这种访问方式可能效率有些低。也就是说,一个集合类应该实现RandomAccess接口。这是一个没有方法的标记接口。
例如,ArrayList实现了List和RandomAccess,但是LinkedList只实现了List接口。
在set中元素不会被插入到特定的位置,并且不允许重复的元素。SortedSet允许按顺序的迭代,NavigableSet含有寻找元素邻居的方法。
Queue会记住插入的顺序,但是只能在尾端插入元素,头部删除它们。Deque(双端队列)
所有的集合接口都是泛型类型的,带有表示元素类型的类型参数。
Collections类的有用方法:
P237 !
2、迭代器
1 Collection<String> coll = ...; 2 Iterator<String> iter = coll.iterator(); 3 while(iter.hasNext()){ 4 String element = iter.next();
iter.remove(); 5 }
remove方法移除了迭代器返回的最后一个元素,并不是迭代器指向的元素。在中间没有调用next或previous时不能连续两次调用remove
1 List<String> friends = new LinkedList<>(); 2 ListIterator<String> iter = friends.listIterator(); 3 iter.add("a");// a| 4 iter.add("b");// a b | 5 iter.previous();// a|b 6 iter.add("c");// a | c 7 //ListIterator和链表一起使用 8 //在迭代之前添加元素,将被访问的元素设置为不同值,向后回溯
如果你用多个迭代器访问一个数据结构,其中一个使数据结构发生改变,那么其他的迭代器可能会失效。如果继续使用的话,一个无效的迭代器可能抛出ConcurrentModificationException
3、set
set可以高效的检测一个值是不是它的元素(是否包含在内contains())。但是不记得元素添加的顺序。当顺序无关紧要时,set是很有用的。
如果想要按顺序便利集合,可以使用TreeSet。set的元素必须实现Comparable接口,或者在构造函数中提供Comparator
TreeSet类实现了SortedSet和NavigableSet接口
P241 SortedSet和NavigableSet方法!
4、Map
map存储键和值之间的联系。调用put方法建立新的联系,或者改变已存键所对应的值(put方法可以更新键下的值)。
不用按顺序访问用HashMap,如果要按序访问用TreeMap
int count = counts.get("a"); //如果键不存在get返回Null,当值拆箱时会出空指针异常
int count = counts.getOrDefault("a",0);//建议使用
计数器,当存在就加一:
counts.merge(word, 1, Integer::sum);
如果word键之前不存在,就将word与1联系起来,否则就用Integer::sum函数将之前的值加1
P243 Map方法! 没看懂。
1 //迭代Map 2 for(Map.Entry<String, Integer> entry : counts.entrySet()){ 3 String k = entry.getKey(); 4 Integer V = entry.getValue(); 5 } 6 //或者 7 counts.forEach((k,v)->{k,v处理});
5、其他集合
Properties类可以容易地使用纯文本格式保存和加载的映射。通常用来存储项目的配置选项。
1 Properties settings = new Porperties(); 2 settings.put("width", "200"); 3 settings.put("title", "hello"); 4 try(OutputStream out = Files.newOutputStream(Path)){ 5 settings.store(out, "Properties"); 6 }
属性文件使用ASCII编码而不是UTF-8,注释以#或!开头,不在范围的字符会Uniode转义格式写入
1 //从文件加载属性 2 try(InputStream in = Files.newInputStream(path)){ 3 settings.load(in); 4 } 5 String tilte = settings.getProperty("tilte","New Document");
System.getProperties()获得系统properties对象。System.getenv()获得Java虚拟机环境变量。
6、其他集合
位组(BitSet):用long数组存储,提供了方法来获取bit,有交集和并集操作
枚举set,枚举Map
栈、队列、线程安全队列、优先级队列(PriorityQueue)
1 PriorityQueue<Job> jobs = new PriorityQueue<>(); 2 jobs.add(new Job()); 3 4 Job job = jobs.remove();//首先移除优先权为1,最紧急的作业
弱哈希映射表WeakHashMap
当一个值所对应的键不再使用时,会被单独回收。本来垃圾回收只会回收整个Map,现在当键的唯一引用来自哈希表条目时,就删除键值对。
视图、范围(用tailSet,headSet可以生成没有上下界的视图)NavigableSet<String> nAndByond = words.tailSet("n");使用NavigableSet接口可以选择每个界限是否应该包含在内
空视图、单例视图、不可修改视图
※使用java.util.concurrent包中提供的并发访问数据结构,原理同步视图