ITPub博客

首页 > 移动开发 > ANDROID > 两个小问题深入浅出List的性能问题

两个小问题深入浅出List的性能问题

原创 ANDROID 作者:山有木xi 时间:2023-02-25 20:32:24 0 删除 编辑

最近在开发中发现,在使用时,很多插件、库是需要我们传入 List 数据的,而一般都会提供数据重置方法,而我发现大部分库的数据重置方法采用的是先 clear 再 addall ,就想到 问题1:addAll的性能会更好吗?

我的推测是,在 resetData 时,如果使用 addAll 就必须先 clear ,这样肯定会损失一定的性能的,如果直接重新 new 一个的话,似乎性能方面会更好,而集合的 addAll 此方法按照指定  collection  的迭代器所返回的元素顺序,将该  collection  中的所有元素添加到此列表的尾部。

让我们来看看实际的测试结果,先看看addAll的情况,代码如下:

private fun test() {
    val list= mutableListOf<String>()
    for (i in 1 .. 1000000){
        list.add("")
    }
    Timber.e("初始时间===${monthDayFormat.format(System.currentTimeMillis())}")
    testList.clear()
    testList.addAll(list)
    Timber.e("结束时间===${monthDayFormat.format(System.currentTimeMillis())}")
}

运行结果如下:

再来看看直接覆盖的情况,代码如下:

private fun test() {
    val list= mutableListOf<String>()
    for (i in 1 .. 1000000){
        list.add("")
    }
    Timber.e("初始时间===${monthDayFormat.format(System.currentTimeMillis())}")
    testList.clear()
    testList=list
    Timber.e("结束时间===${monthDayFormat.format(System.currentTimeMillis())}")
}

运行结果如下:


  可以看到,在数据量越大的情况下,直接覆盖比addAll要快很多,但是这样子就又有一个新的问题,在很多情况下,特别是第三方库中的List,普遍使用final类型的情况就不能直接覆盖。这个时候就想到 问题2:final的好处是什么

  可以查到的数据显示,使用关键字 final 将有助于编译器静态优化代码,这最终可能导致更快的代码,但是他能提高的速度远远没有到达非常快的速度,让我们看下面的代码

public class FinalTest {
    public static final int N_ITERATIONS = 1000000;
    public static String testFinal() {
        final String a ="a";
        final String b ="b";
        return a + b;
    }
    public static String testNonFinal() {
        String a ="a";
        String b ="b";
        return a + b;
    }
    public static void main(String[] args) {
        long tStart, tElapsed;
        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method with finals took" + tElapsed +" ms");
        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testNonFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method without finals took" + tElapsed +" ms");
    }
}

看看他的运行结果:

Method with finals took 5 ms
Method without finals took 273 ms

  在高度优化的的程序下可能会有影响,到这个时候好像就没有什么问题了,但是我又突然想到开发的一个知识点 List集合的区别

       Java 集合就像一个容器,主要由 2 大体系构成,分别是 Collection 体系和 Map 体系,其中 Collection 和 Map 分别是 2 大体系中的顶层接口 Collection 主要有三个子接口,分别为 List( 列表 ) 、 Set( 集 ) 、 Queue( 队列 ) 。其中, List 、 Queue 中的元素有序可重复,而 Set 中的元素无序不可重复, List 中主要有 ArrayList 、 LinkedList 两个实现类。

  其中 ArrayList 底层通过数组实现,随着元素的增加而动态扩容, ArrayList 实现 RandomAccess ,获得了快速随机访问存储元素的功能, ArrayList 的特点是容量不固定,随着容量的增加而动态扩容

  而 LinkedList 底层通过链表来实现,随着元素的增加不断向链表的后端增加节点,它的特点是读取的速度慢写入的速度快





来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917874/viewspace-2937032/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: Android中invalidate
请登录后发表评论 登录
全部评论
Oracle OCA(Java),IBM高级工程师认证,中国软件行业人才(高级c语言),高级Android工程师,对数据库并发与性能调优也有一定了解

注册时间:2019-04-25

  • 博文量
    147
  • 访问量
    390769