集合类List使用注意事项

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/

 

posted @ 2021-12-13 11:28  白玉神驹  阅读(98)  评论(0)    收藏  举报