`
bo_hai
  • 浏览: 563809 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

讨论:如何高效使用List

 
阅读更多

 大家都知道Java list 的实现类有两个,分别是:ArrayList、LinkedList。实际工作中,使用最多的是ArrayList。ArrayList 的底次实现是数据,LinkedList的层次是链表。书上告诉我们:当需要在List中间插入数据时,应该使用LinkedList,ArrayList 有高效的访问效率。真的是这样的吗?看如下的代码:

List<Integer> arrays = new ArrayList<Integer>();
for (int i = 0; i < 10000; i++) {
	arrays.add(i);
}

  向一个List中插入10000个数据,应该使用ArrayList?我们来简单的分析一下ArrayList的代码:

 

    public ArrayList(int initialCapacity) {
	super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
	this.elementData = new Object[initialCapacity];
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
	this(10);
    }

  可以看出:ArrayList 存储数组的初始长度是 10 。那么,当数组满了时,ArrayList是怎么样做的呢?继续看代码:

 

 

    public boolean add(E e) {
	ensureCapacity(size + 1);  // Increments modCount!!
	elementData[size++] = e;
	return true;
    }

 

    public void ensureCapacity(int minCapacity) {
	modCount++;
	int oldCapacity = elementData.length;
	if (minCapacity > oldCapacity) {
	    Object oldData[] = elementData;
	    int newCapacity = (oldCapacity * 3)/2 + 1;
    	    if (newCapacity < minCapacity)
		newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
	}
    }

  注:当向ArrayList中添加一个数据时,调用 ensureCapacity 方法,判断数组的空间是否能满足存储当前数据的条件,如不能,使用Arrays.copyOf(oldArray,newLength) 把数组中的旧数据copy到一个新的、更长的数组中。在copy过程中,是这么做的:首先CPU寻址:找到一个连续的、空白的、满足指定长度的空闲内存块,找到后,进行搬数据操作。这个过程会随着数据越来越多,数组的长度越来越大,效率会急剧下降。因此,当我们使用List来存储“大数据”时,首选LinkedList。好处是:LinkedList 是使用链表来存储数据,向LinkedList中插入数据时,不会出现寻址和copy数据的操作,更正确的说,会更快的找到满足存储条件的空闲块。基于上述理由:代码修改为:

List<Integer> arrays = new LinkedList<Integer>();
for (int i = 0; i < 1000; i++) {
	arrays.add(i);
}

 LinkedList 也存在不足之处:如下代码:

for (Integer val : arrays) {
	System.out.println(val);
}

 循环遍历List。如果List是LinkedList实现的,每遍历一个元素,都要寻找下个数据的地址,因为元素并不是存储在连续的内存块中。这时的寻址也会很“消费时间”。优化方法:把生成后的LinkedList再放入一个ArrayList中,生成一个ArrayList 对象,ArrayList 的存储在内存块中是连续存放的,在遍历时,不会因寻址“浪费时间”了。优化后的代码如下:

List<Integer> arrays = new LinkedList<Integer>();
for (int i = 0; i < 1000; i++) {
	arrays.add(i);
}
arrays = new ArrayList<Integer>(arrays);
for (Integer val : arrays) {
	System.out.println(val);
}

  上面讲到的方法,并没有进行严格的测试,肯定会有不足之处。欢迎大家批评!

 

3
0
分享到:
评论
16 楼 bo_hai 2013-12-06  
yixiandave 写道
yanh0606 写道
6楼可以试试插入效率,我试着差别很大的,代码拿六楼的稍微一该,如下:
public static void main(String[] args)
    {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        System.out.println("for..each test");
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
        {
            listA.add(RandomStringUtils.random(5, true, true));
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++)
        {
            listB.add(RandomStringUtils.random(5, true, true));
        }
        long time3 = System.currentTimeMillis();
        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

LinkedList在头部插入效率上必然比ArrayList有天然优势。如果是末端添加应该是ArrayList优于LinkedList,另外ArrayList在随机寻址有巨大优势
我在6楼贴的测试只是证明为了顺序遍历一个LinkedList完全没必要转为ArrayList再遍历

要测试就彻底一点吧

测试1:默认大小的List末端插入效率测试:
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listA.add("aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listB.add("aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

结果:
LinkedList:156
ArrayList:78

ArrayList毫无鸭梨碾压

测试2:设置初始容器大小后的插入测试(有点欺负LinkedList了,他没有这种构造方法):
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>(1000000);
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listA.add("aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listB.add("aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

完全的碾压。。。不忍直视
LinkedList:141
ArrayList:15

测试3:头部插入,LinkedList挽回尊严的时刻。之前100万的数量级等了5分钟都没结果,看来消耗确实巨大。缩小到10万
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listA.add(0, "aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listB.add(0, "aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

毫无鸭梨的碾压
LinkedList:15
ArrayList:4781

测试4:中部插入,LinkedList根据下标寻址需要从头遍历,严重影响了其性能
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listA.add(listA.size()/2, "aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listB.add(listB.size()/2, "aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

不出意外
LinkedList:30531
ArrayList:2188


   严谨的精神,值得我学习。
15 楼 yixiandave 2013-12-06  
yanh0606 写道
6楼可以试试插入效率,我试着差别很大的,代码拿六楼的稍微一该,如下:
public static void main(String[] args)
    {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        System.out.println("for..each test");
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
        {
            listA.add(RandomStringUtils.random(5, true, true));
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++)
        {
            listB.add(RandomStringUtils.random(5, true, true));
        }
        long time3 = System.currentTimeMillis();
        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

LinkedList在头部插入效率上必然比ArrayList有天然优势。如果是末端添加应该是ArrayList优于LinkedList,另外ArrayList在随机寻址有巨大优势
我在6楼贴的测试只是证明为了顺序遍历一个LinkedList完全没必要转为ArrayList再遍历

要测试就彻底一点吧

测试1:默认大小的List末端插入效率测试:
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listA.add("aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listB.add("aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

结果:
LinkedList:156
ArrayList:78

ArrayList毫无鸭梨碾压

测试2:设置初始容器大小后的插入测试(有点欺负LinkedList了,他没有这种构造方法):
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>(1000000);
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listA.add("aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            listB.add("aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

完全的碾压。。。不忍直视
LinkedList:141
ArrayList:15

测试3:头部插入,LinkedList挽回尊严的时刻。之前100万的数量级等了5分钟都没结果,看来消耗确实巨大。缩小到10万
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listA.add(0, "aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listB.add(0, "aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

毫无鸭梨的碾压
LinkedList:15
ArrayList:4781

测试4:中部插入,LinkedList根据下标寻址需要从头遍历,严重影响了其性能
    public void testInsert() {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listA.add(listA.size()/2, "aaa");
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            listB.add(listB.size()/2, "aaa");
        }
        long time3 = System.currentTimeMillis();

        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }

不出意外
LinkedList:30531
ArrayList:2188
14 楼 yanh0606 2013-12-06  
6楼可以试试插入效率,我试着差别很大的,代码拿六楼的稍微一该,如下:
public static void main(String[] args)
    {
        List<String> listA = new LinkedList<String>();
        List<String> listB = new ArrayList<String>();
        System.out.println("for..each test");
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
        {
            listA.add(RandomStringUtils.random(5, true, true));
        }
        long time2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++)
        {
            listB.add(RandomStringUtils.random(5, true, true));
        }
        long time3 = System.currentTimeMillis();
        System.out.println("LinkedList:" + (time2 - time1));
        System.out.println("ArrayList:" + (time3 - time2));
    }
13 楼 bo_hai 2013-12-05  
一个java程序员 写道
喜欢这样的文章,呵呵,不喜欢千篇一律那种。


谢谢!
12 楼 一个java程序员 2013-12-05  
喜欢这样的文章,呵呵,不喜欢千篇一律那种。
11 楼 Grumpy 2013-12-04  
1.ArrayList可以设定初始容量,即使需要扩容也是调用System.arrayCopy,速度比较快。
2.除了通过下标访问速度较慢,LinkedList在insert的过程中需要new一个Entry,不管是空间还是效率,都会慢很多。
10 楼 13shu 2013-12-04  
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 

arrays = new ArrayList<Integer>(arrays);
其实也是遍历了一次LinkedList
个人理解:
如果数据插入很频繁,而且获取时数据会被删除(比如队列)这样的情况下很适合LinkedList,其他情况下貌似只能使用ArrayList
9 楼 liulijun.cn.2011 2013-12-04  
bo_hai 写道
liulijun.cn.2011 写道
独孤小败 写道
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

ArrayList初始化的时候有个参数,new ArrayList<Integer>(1000); 这样就不存在扩容的过程了,因为一开始它就申明这么多空间,new ArrayList<Integer>(arrays) 是一个道理.

不好意思,问一下。
如果初始声明了长度例如 1000, 但list中的数据是查询DB来的。 而DB中实际数据只有500条。
多余的那个500个数据空间怎样处理?



ArrayList.trimToSize() 可以解决你的问题。

   
8 楼 bo_hai 2013-12-04  
liulijun.cn.2011 写道
独孤小败 写道
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

ArrayList初始化的时候有个参数,new ArrayList<Integer>(1000); 这样就不存在扩容的过程了,因为一开始它就申明这么多空间,new ArrayList<Integer>(arrays) 是一个道理.

不好意思,问一下。
如果初始声明了长度例如 1000, 但list中的数据是查询DB来的。 而DB中实际数据只有500条。
多余的那个500个数据空间怎样处理?



ArrayList.trimToSize() 可以解决你的问题。
7 楼 liulijun.cn.2011 2013-12-04  
独孤小败 写道
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

ArrayList初始化的时候有个参数,new ArrayList<Integer>(1000); 这样就不存在扩容的过程了,因为一开始它就申明这么多空间,new ArrayList<Integer>(arrays) 是一个道理.

不好意思,问一下。
如果初始声明了长度例如 1000, 但list中的数据是查询DB来的。 而DB中实际数据只有500条。
多余的那个500个数据空间怎样处理?
6 楼 yixiandave 2013-12-04  
因为LinkedList的toArray()实现依然需要遍历一遍,如果同为一次遍历,即使for..each处理ArrayList的效率稍高于LinkedList,但是将LinkedList转为ArrayList遍历一遍产生的开销无法忽略。除非ArrayList需要多次遍历

然而经过我的机器测试,100万个随机字符串组成的队列分别放入LinkedList和ArrayList,分别进行for..each遍历效率不相上下,多次测试后都稳定在47毫秒上下,并且没有体现出哪个效率更高的情况,无奈机器配置不好,想测试1000万规模的时候直接OutOfMemory了。

但就此看出,即使是1000万级别的数据,遍历一遍时间差也不会超过10毫秒,即使是为了ArrayList遍历的那一点点效率就将LinkedList多遍历一次实在得不偿失。

给出测试代码,当然不够严谨就是了,依赖jar包:commons-lang:commons-lang:2.6
仅仅是用来生成随机字符串(偷懒ing)

    @Test
    public void test(){
        List<String> listA = new LinkedList<String>();
        for(int i=0;i<1000000;i++){
            listA.add(RandomStringUtils.random(5,true,true));
        }
        List<String> listB = new ArrayList<String>(listA);
        System.out.println("for..each test");
        long time1 = System.currentTimeMillis();
        for (String s:listA){
        }
        long time2 = System.currentTimeMillis();
        for (String s:listB){
        }
        long time3 = System.currentTimeMillis();
        System.out.println("LinkedList:"+(time2-time1));
        System.out.println("ArrayList:"+(time3-time2));
    }
5 楼 bo_hai 2013-12-04  
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?


    public ArrayList(Collection<? extends E> c) {
	elementData = c.toArray();
	size = elementData.length;
	// c.toArray might (incorrectly) not return Object[] (see 6260652)
	if (elementData.getClass() != Object[].class)
	    elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

arrays = new ArrayList<Integer>(arrays);

这样只会copy 一次。
4 楼 yixiandave 2013-12-04  
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

没完全理解你的意思,是不是代码顺序贴错了

将LinkedList作为构造参数传入ArrayList的构造方法,当然是直接创建相同容量的数组,然后将LinkedList中的元素分别copy到ArrayList中。因为初始大小设定的足够大,所以不存在扩容的过程,但是copy数据是必要的

我们来看看源码:
这是ArrayList带一个Collection的构造方法,我们看到调用了构造参数的.toArray()方法
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

我们再来看看LinkedList的toArray()实现:
    public Object[] toArray() {
        Object[] result = new Object[size];
        int i = 0;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        return result;
    }

实际上内部依然对LinkedList做了一次寻址、遍历操作
所以为了遍历LinkedList而将LinkedList转换为ArrayList实际上效率低于直接遍历LinkedList。当然,需要注意遍历LinkedList一定要使用for..each的写法
3 楼 独孤小败 2013-12-04  
kt431128 写道
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

ArrayList初始化的时候有个参数,new ArrayList<Integer>(1000); 这样就不存在扩容的过程了,因为一开始它就申明这么多空间,new ArrayList<Integer>(arrays) 是一个道理.
2 楼 lianglove_0 2013-12-04  
Linkedlist 遍历的时候用迭代器吧
1 楼 kt431128 2013-12-04  
arrays = new ArrayList<Integer>(arrays); 
这样把
List<Integer> arrays = new LinkedList<Integer>(); 
for (int i = 0; i < 1000; i++) { 
    arrays.add(i); 
}  数据放入到ArrayList中,ArrayList不会存在扩容、拷贝数据的过程吗?

相关推荐

    C# List使用总结

    通过这些详细讨论和实际代码示例,我们可以更深入地理解C#中`List&lt;T&gt;`、`ArrayList`和`LinkedList&lt;T&gt;`的使用,从而在实际项目中选择最合适的集合类型。在进行性能优化时,应根据具体需求考虑这些集合类的不同特性。

    fast test concept

    本文档主要讨论了在多评估列表模式下,如何通过各种方法优化测试性能。这些方法的可用性取决于所使用的CMW500版本。 多评估列表模式是一种在单次测量中获取一组测量结果的方法,适用于一系列分析设置。这些分析设置...

    Pro Android学习:list widget小例子

    总的来说,"Pro Android学习:list widget小例子"是一个关于如何在Android平台上使用List Widget的实战教程。通过这个例子,开发者可以学习到如何创建自定义Adapter、配置ListView,以及如何实现Widget的动态更新。...

    List_Control.rar_list control_listcontrol

    在“应用ListControl来对数据库操作”这个主题中,我们将重点讨论如何利用List Control显示和操作数据库中的数据。通常,这涉及到以下几个步骤: 1. **初始化List Control**:在创建List Control时,需要设置其样式...

    struts2对于checkboxlist的换行

    这篇博客讨论的是如何在Struts2中处理`checkboxlist`的换行问题,这在创建多列或美观的表单布局时非常有用。 `checkboxlist`在Struts2中通常与一个Action类中的属性关联,用于收集用户的多选数据。在HTML中,复选框...

    VS2010 C++学习(6):ListCtrl用法及ADO方式读写Access程序文档

    在本文中,我们将深入探讨如何在Visual Studio 2010 (VS2010)的C++环境中使用ListCtrl控件以及ADO(ActiveX Data Objects)技术来读写Access数据库程序文档。ListCtrl是Windows API中的一种控件,常用于显示列表形式...

    VirtualList.7z

    这里我们讨论的“VirtualList.7z”文件是与duilib库相关的,它是一个C++库,主要用于Windows平台上的GUI开发。这个压缩包包含了一个经过修改的CListUI控件,该控件已经扩展以支持虚拟列表功能,能够高效地显示多达50...

    可编辑ListCtrl控件

    在Windows编程领域,ListCtrl...通过以上讨论,我们对可编辑ListCtrl控件有了全面的理解,包括其核心功能、实现方式以及可能的扩展。在实际开发中,灵活运用这些知识能帮助我们创建出更高效、易用的Windows应用程序。

    java开发List提高效率

    3. 使用-third-party 库:使用成熟的 third-party 库可以提高开发效率,例如,使用 Guava 库可以简化字符串处理和数据转换操作。 提高 List 转换效率需要选择合适的方法和数据结构,并合理使用 third-party 库和 ...

    C# ObservableCollection与List

    这些文件与`ObservableCollection`和`List&lt;T&gt;`的讨论直接关联性不大,但可以推测这是一个可能使用了数据绑定和区域导航的C#项目,其中可能涉及到`ObservableCollection`的使用。在这样的项目中,`...

    mybatis collection list string

    标题 "mybatis collection list string" 暗示了我们讨论的主题是关于MyBatis框架中与集合(List)和字符串(String)处理相关的问题。在MyBatis这个强大的持久层框架中,集合和字符串的使用非常常见,尤其是在进行数据库...

    Set用法及与List的区别

    2. **添加元素**:使用`add()`方法添加元素,如果元素已经存在,`add()`方法将返回`false`。 ```java set.add("Element3"); ``` 3. **删除元素**:使用`remove()`方法删除元素。 ```java set.remove("Element1...

    List和SeqList

    在学习链表的过程中,了解和实践这两种链表实现(List和SeqList),并结合STL的`std::list`,可以帮助开发者熟练掌握链表的使用,并在实际问题中选择最适合的数据结构。通过分析和比较它们各自的特性,我们可以更好...

    SharedPreferences的形式在缓存中维护两个List,对其进行增删等操作

    然而,根据提供的信息,这里主要讨论的是如何使用`SharedPreferences`来维护`List&lt;String&gt;`。 总结来说,`SharedPreferences`可以借助`Gson`库间接地存储和操作`List&lt;String&gt;`,但这种方法更适合轻量级的使用场景。...

    C++高效编程(中文版)

    7. **STL的使用**:STL包括容器(如vector、list、set等)、迭代器、算法和函数对象等,是C++高效编程的重要工具。书中可能会深入解析STL的工作原理和最佳实践,以提高代码的效率和可读性。 8. **C++11及后续版本的...

    SharePoint 2007中的List 详细解析

    总之,SharePoint 2007中的List是一个强大且灵活的信息管理工具,它支持多种数据类型、视图定制、集成外部数据源以及与其他SharePoint功能的紧密协作,使得团队协作和信息管理变得更加高效和便捷。通过熟练掌握List...

    java list 过滤

    博客中提到的“源码”标签可能意味着文章会深入到Java集合框架的内部实现,讨论如何优化过滤操作的性能,或者分析`List`接口及流API的源代码,帮助读者理解其工作原理。 至于“工具”标签,可能暗示文章介绍了某些...

    c#之数组和list转换

    了解了转换方法后,我们来讨论一下何时选择数组,何时选择List&lt;T&gt;: - **数组**:适合在元素数量确定且不经常变化的情况下使用。数组的访问速度通常比List&lt;T&gt; 快,因为它的内存是连续分配的,对于需要高效遍历或...

    Struts2 iterator 标签遍历 Map,List,数组(三十六)

    接下来,我们讨论如何遍历List。List是一种有序的集合,`iterator`标签通过`status`属性可以提供迭代状态信息,如当前元素的索引等。假设我们有一个名为`myList`的List,我们可以这样遍历: ```jsp &lt;s:iterator ...

Global site tag (gtag.js) - Google Analytics