Java集合中的细节

integer数据对比

  对于Integer var = ? 在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。

Array的subList

  ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList. 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。

List变Array

  使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素个数大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。

  正例:

1 List<String> list = new ArrayList<String>(2);
2 list.add("guan");
3 list.add("bao");
4 String[] array = new String[list.size()];
5 array = list.toArray(array);

Array变List

  使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。 说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。

1 String[] str = new String[] { "you", "wu" }; 
2 List list = Arrays.asList(str);

  第一种情况:list.add("yangguanbao"); 运行时异常。

  第二种情况:str[0] = "gujin"; 那么list.get(0)也会随之修改。

泛型

  泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,作为接口调用赋值时易出错。 说明:扩展说一下PECS(Producer Extends Consumer Super)原则:第一、频繁往外读取内容的,适合用<? extends T>。第二、经常往里插入的,适合用<? super T>。

Foreach

  不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。

  正例:

1 Iterator<String> iterator = list.iterator();
2 while (iterator.hasNext()) {
3     String item = iterator.next();
4     if (删除元素的条件) {
5         iterator.remove();
6     }
7 }

  反例:

1 List<String> list = new ArrayList<String>();
2 list.add("1");
3 list.add("2");
4 for (String item : list) {
5     if ("1".equals(item)) {
6         list.remove(item);
7     }
8 }

排序

  在JDK7版本及以上,Comparator要考虑相等情况,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常,下例中没有处理相等的情况,实际使用中可能会出现异常

1 new Comparator<Student>() {
2     @Override
3     public int compare(Student o1, Student o2) {
4         return o1.getId() > o2.getId() ? 1 : -1;
5     }
6 };

遍历Map

  使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。

Map可否存null

原文地址:https://www.cnblogs.com/guanghe/p/10768058.html