Arrays.asList使用注意事项
1. 不能直接使用Arrays.asList来转换基本类型数组;
//解决1,装箱
int[] arr1 = {1, 2, 3};//直接声明为包装类则可使用Arrays.asList直接转
List list1 = Arrays.stream(arr1).boxed().collect(Collectors.toList());
2. Arrays.asList返回的List是Arrays的内部类ArrayList(继承自AbstractList没有重写add方法,而父类add方法则是抛出UnsupportedOperationException)不支持增删操作;
3. 对原始数组的修改会影响获取的List;
//解决2和3,实现解耦,不再影响
List list = new ArrayList(Arrays.asList(arr));
List.subList使用注意事项
1. List.subList切片返回的list是原始List的视图,会与原始List相互影响。(返回的List强引用原始List,大量保存会导致OOM)
2. 解决一:构造方法中传入subList,构建独立ArrayList;
//List<Integer> subList = new ArrayList<>(list.subList(1, 4));
3. 解决二:使用Java8的Stream的skip何limitAPI跳过流中元素以及限制流中元素的个数;
//List<Integer> subList = list.stream().skip(1).limit(3).collect(Collectors.toList());
HashMap、ArrayList、LinkedList数据结构使用注意事项
1. 对大List进行单值(分组区间)搜索,HashMap性能优于ArrayList,其中Key是搜索的值(不同的区间),Value是原始对象;
2. 使用ObjectSizeCalculator 工具或MAT 工具分析堆看出内存占用上HashMap比ArrayList要大;所以使用时需考虑空间换时间还是时间换空间;
3. ArrayList随机访问性能高,LinkedList元素插入性能高,但在各种常用场景下,ArrayList性能都要优于LinkedList.
//LinkedList源码
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
从LinkedList源码中看出,插入操作的时间复杂度O(1)的前提是,已经有了那个要插入节点的指针。但在实现的时候,要通过循环获取那个节点的Node,然后再执行插入操作;所以在使用过程中进行性能测试评估以下。
ArrayList的remove方法注意事项
1. Integer类型的ArrayList的remove方法删除元素,传入Integer类型调用boolean remove(Object o)方法表示删除元素,传入int类型调用E remove(int index)方法删除相对应索引位置的元素;
2. 循环遍历List,调用remove方法删除元素会遇到ConcurrentModificationException;
原因:①源码中看出ArrayList中维护的modeCount会发生结构化修改,也就是modCount在add/remove时会增加(这个list集合修改的次数);
②当循环过程中,(即next或者remove时调用checkForComodification;
③发现expectedModCount(这个迭代器修改的次数即初始)和modCount(这个集合实际修改的次数即当前)不相等,抛出ConcurrentModificationException.
解决一:使用ArrayList的迭代器iteratior,并调用remove方法
解决二:使用Java8的removeIf方法进行删除操作;
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
removeIf的使用
List<User> list = getList();
int first_index = 0;
List<User> tempList = new ArrayList(list);
tempList.remove(first_index);//去除第一个用户 (这里必须是int类型)//方式一
Iterator<User> iterator = tempList.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
if (user.getAge() >= 18)
iterator.remove();
}
//方式二
tempList.removeIf(
user-> user.getAge() >= 18
);
数据结构时间复杂度比较
https://www.bigocheatsheet.com/