java业务开发常见错误100例list笔记

使用 List.subList 进行切片操作居然会导致 OOM?

private static List> data = new ArrayList<>();
private static void oom() {
    for (int i = 0; i < 1000; i++) {
        List rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());
        data.add(rawList.subList(0, 1));
    }
}

删除子 List 中的元素影响到了原始 List;尝试为原始 List 增加数字 0 之后再遍历子 List,会出现 ConcurrentModificationException。
List list = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
List subList = list.subList(1, 4);
System.out.println(subList);
subList.remove(1);
System.out.println(list);
list.add(0);
try {
    subList.forEach(System.out::println);
} catch (Exception ex) {
    ex.printStackTrace();
}

既然 SubList 相当于原始 List 的视图,那么避免相互影响的修复方式有两种: 修复后代码输出如下: 一种是,不直接使用 subList 方法返回的 SubList,而是重新使用 new ArrayList,在构 造方法传入 SubList,来构建一个独立的 ArrayList; 另一种是,对于 Java 8 使用 Stream 的 skip 和 limit API 来跳过流中的元素,以及限制 流中元素的个数,同样可以达到 SubList 切片的目的。  //方式一: List subList = new ArrayList<>(list.subList(1, 4));

//方式二:

List collect = list.stream().skip(1).limit(4).collect(Collectors.toList());
对于数组,随机元素访问的时间复杂度是 O(1),元素插入操作是 O(n);
对于链表,随机元素访问的时间复杂度是 O(n),元素插入操作是 O(1)。

随机 插入操作居然也是 LinkedList 落败,耗时 9.3 秒,ArrayList 只要 1.5 秒:抛开算法层面不谈,由于 CPU 缓存、内存连续性等问题,链表这种数 据结构的实现方式对性能并不友好,即使在它最擅长的场景都不一定可以发挥威力。

int elementCount = 100000;
int loopCount = 100000;
StopWatch stopWatch = new StopWatch();
stopWatch.start("linkedListGet");
linkedListGet(elementCount, loopCount);
stopWatch.stop();
stopWatch.start("arrayListGet");
arrayListGet(elementCount, loopCount);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());

StopWatch stopWatch2 = new StopWatch();
stopWatch2.start("linkedListAdd");
linkedListAdd(elementCount, loopCount);
stopWatch2.stop();
stopWatch2.start("arrayListAdd");
arrayListAdd(elementCount, loopCount);
stopWatch2.stop();
System.out.println(stopWatch2.prettyPrint());
//LinkedList访问
private static void linkedListGet(int elementCount, int loopCount) {
    List list = IntStream.rangeClosed(1, elementCount).boxed().collect(Collectors.toCollection(LinkedList::new));
    IntStream.rangeClosed(1, loopCount).forEach(i -> list.get(ThreadLocalRandom.current().nextInt(elementCount)));
}
//ArrayList访问
private static void arrayListGet(int elementCount, int loopCount) {
    List list = IntStream.rangeClosed(1, elementCount).boxed().collect(Collectors.toCollection(ArrayList::new));
    IntStream.rangeClosed(1, loopCount).forEach(i -> list.get(ThreadLocalRandom.current().nextInt(elementCount)));
}
//LinkedList插入
private static void linkedListAdd(int elementCount, int loopCount) {
    List list = IntStream.rangeClosed(1, elementCount).boxed().collect(Collectors.toCollection(LinkedList::new));
    IntStream.rangeClosed(1, loopCount).forEach(i -> list.add(ThreadLocalRandom.current().nextInt(elementCount)));
}
//ArrayList插入
private static void arrayListAdd(int elementCount, int loopCount) {
    List list = IntStream.rangeClosed(1, elementCount).boxed().collect(Collectors.toCollection(ArrayList::new));
    IntStream.rangeClosed(1, loopCount).forEach(i -> list.add(ThreadLocalRandom.current().nextInt(elementCount)));
}

调用类型是 Integer 的 ArrayList 的 remove 方法删除元素,传入一个 Integer 包装类 的数字和传入一个 int 基本类型的数字,结果一样吗?

List list = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList()); Collections.shuffle(list);

System.out.println(list);
list.remove(1);
System.out.println(list);
list.remove(Integer.valueOf(1));
System.out.println(list);

你可能感兴趣的:(java8,javase,java,list)