优化: 声明一个新的List
String[] arr = {"1", "2", "3"}; List list = new ArrayList(Arrays.asList(arr));ArrayList的subList 在list有个内部类, 这个sublist没有创建新的list, 直接用的list。 所以修改sublist和list会相互影响。
解决方法: 1, 不直接使用subList方法返回的SubList,而是重新使用new ArrayList,在构造方法传入SubList,来构建一个独立的ArrayList; 2, 对于Java 8使用Stream的skip和limit API来跳过流中的元素,以及限制流中元素的个数,同样可以达到SubList切片的目的
//方式一: List<Integer> subList = new ArrayList<>(list.subList(1, 4)); //方式二: List<Integer> subList = list.stream().skip(1).limit(3).collect(Collectors.toList());ArrayList和HashMap查找对比
要对大List进行单值搜索的话,可以考虑 使用HashMap,其中Key是要搜索的值,Value是原始对象,会比使用ArrayList有非常明显的性能优势。ArrayList在内存占用上性价比很高,77%(大约)是实际的数据,而HashMap的“含金量”只有22%(大约)。LinkedList和ArrayList插入和查询对比
书本上的解释:
对于数组,随机元素访问的时间复杂度是O(1),元素插入操作是O(n); 查询快 对于链表,随机元素访问的时间复杂度是O(n),元素插入操作是O(1)。 插入快
实际: 数组和链表 查询和插入都比链表快。
插入操作的时间复杂度是O(1)的前提是,你已经有了那个要插入节点的指针。但,在实现的时候,我们需要先通过循环获取到那个节点的Node,然后再执行插入操作。前者也是有开销的,不可能只考虑插入操作本身的代价: 总结: 1, Arrays.asList得到的是Arrays的内部类ArrayList,List.subList得到的是ArrayList的内部类SubList,不能把这两个内部类转换为ArrayList使用。 2, Arrays.asList直接使用了原始数组,可以认为是共享“存储”,而且不支持增删元素;List.subList直接引用了原始的List,也可以认为是共享“存储”,而且对原始List直接进行结构性修改会导致SubList出现异常。 3, 对Arrays.asList和List.subList容易忽略的是,新的List持有了原始数据的引用,可能会导致原始数据也无法GC的问题,最终导致OOM
问题:
调用类型是Integer的ArrayList的remove方法删除元素,传入一个Integer包装类的数字和传入一个int基本类型的数字,结果一样吗?循环遍历List,调用remove方法删除元素,往往会遇到ConcurrentModificationException异常,原因是什么,修复方式又是什么呢?1、使用 ArrayList 的 remove方法,如果传参是 Integer类型的话,表示的是删除元素,如果传参是int类型的话,表示的是删除相对应索引位置的元素。;两个都需要进行数组拷贝,是通过System.arraycopy进行的 2、以foreach为例说,遍历删除实质是变化为迭代器实现,不管是迭代器里面的remove()还是next()方法,都会checkForComodification();而这个方法是判断modCount和expectedModCount是否相等,这个modCount是这个list集合修改的次数,每一次add或者remove都会增加这个变量,然后迭代器每次去next或者去remove的时候检查checkForComodification();发现expectedModCount(这个迭代器修改的次数)和modCount(这个集合实际修改的次数)不相等,就会抛出ConcurrentModificationException,迭代器里面没有add方法,用迭代器时,可以删除原来集合的元素,但是!一定要 用迭代器的remove方法而不是集合自身的remove方法,否则抛异常。
