集合一些方法陷阱

一:asList  数组转ArrayList陷阱:

asList() 源码:

public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
private final E[] a;
ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}

分析:需要注意以下几点:

(1)总所周知,泛型对应的是对象类型,所以 asList(),转ArrayList的时候,数组的元素不能是基本数据类型。

(2) asList(),转换后的List不能进行add(),remove()等操作。返回一个受指定数组支持的固定大小的列表,对返回列表的更改会“直接写”到数组。

public static void test1(){
        //1 asList(),转ArrayList的时候,数组的元素不能是基本数据类型。
        int i[]={11,22,33};
        List intList=Arrays.asList(i);
        System.out.println(intList.size());//结果:1,原因:asList将int i[] 当做了参数
    }

    public static void test2(){
        //2 asList(),转换后的List不能进行add(),remove()等操作。
        //原因:返回一个受指定数组支持的固定大小的列表,对返回列表的更改会“直接写”到数组。
        String s[]={"aa","bb","cc"};
        List<String> sList=Arrays.asList(s);
        sList.add("dd");//error
    }

那么如何正确的将数组转ArraysList呢?

public static void test3(){
        //方法一
        String s[]={"aa","bb","cc"};
        List<String> list1 = new ArrayList<String>(Arrays.asList(s));
        list1.remove(0);//ok

        //方法二:
        List<String> list2 = new ArrayList<String>(s.length);
        list2.addAll(Arrays.asList(s));
        list2.remove(0);//ok

        //方法三:
        List<String> list3 = new ArrayList<String>(s.length);
        Collections.addAll(list3, s);
        System.out.println(list3.remove(0));//ok

        //对于基本类型,可以使用apache commons-lang工具包
        int i[]={11,22,33};
        //先把基本类型转换一下,再用上面3种方法转换
        Integer[] ii = ArrayUtils.toObject(i);
        List<Integer> list4 = new ArrayList<Integer>(ii.length);
        Collections.addAll(list4, ii);//ok
    }  

commons-lang3-3.1.jar 下还有许多类似的工具。如:

二 list.toArray() 陷阱:

//java中的强制类型转换只能转换单个对象,所以不能使用这样的代码将 toArray 返回的数组强转为 String[]
String[] arr=(String[])list.toArray();//会出现java.lang.ClassCastException

正确的用法:

public static void test4(){
        String s[]={"aa","bb","cc"};
        List<String> list1 = new ArrayList<String>(Arrays.asList(s));

        String[] s1 = new String[list1.size()];
        list1.toArray(s1);
        System.out.println(Arrays.toString(s1));
    }  

三  list.subList() 大陷阱:

注意:

(1)用此方法生成列表后,不要再去操作源列表(原因:可分析源码)

(2)用此方法生成列表list1,对list1进行的add,remove,最终还是在操作源列表。

看下面错误案例:

清单1:

public static void test6(){
        String s[]={"aa","bb","cc","dd","ee"};
        List<String> list1 = new ArrayList<String>(Arrays.asList(s));
        List<String> list2 = list1.subList(0, 1);
        System.out.println("list2 size: "+list2.size());

        list1.add("ff");
        System.out.println("list2 size: " + list2.size());//error
    } 

结果: java.util.ConcurrentModificationException

清单2:

public static void test5(){
        String s[]={"aa","bb","cc","dd","ee"};
        List<String> list1 = new ArrayList<String>(Arrays.asList(s));

        List<String> list2 = list1.subList(0, 1);

        System.out.println("list1 size: "+list1.size());
        System.out.println("list2 size: "+list2.size());
        //用此方法生成列表list1,对list1进行的add,remove,最终还是在操作源列表。
        list2.add("ff");

        System.out.println("----操作list2-----");
        System.out.println("list1 size: "+list1.size());
        System.out.println("list2 size: "+list2.size());
    }  

结果:

list1 size: 5

list2 size: 1

----操作list2-----

list1 size: 6

list2 size: 2

需要操作子列表,需要拷贝一份出来:

清单3:

public static void test7(){
        String s[]={"aa","bb","cc","dd","ee"};
        List<String> list1 = new ArrayList<String>(Arrays.asList(s));

        List<String> list2 = new ArrayList<String>(Arrays.asList(s));

        //拷贝一份出来
        list2.addAll(list1.subList(0, 1));

        System.out.println("list1 size: "+list1.size());
        System.out.println("list2 size: "+list2.size());
        list2.add("ff");

        System.out.println("----操作list2-----");
        System.out.println("list1 size: "+list1.size());
        System.out.println("list2 size: "+list2.size());
    }  

结果:

list1 size: 5

list2 size: 6

----操作list2-----

list1 size: 5

list2 size: 7

原文地址:https://www.cnblogs.com/xiaozhuanfeng/p/9581648.html

时间: 2024-10-17 14:41:12

集合一些方法陷阱的相关文章

[ jquery 过滤器 filter(expr|obj|ele|fn) ] 筛选出与指定表达式匹配的元素集合,这个方法用于缩小匹配的范围,用逗号分隔多个表达式

筛选出与指定表达式匹配的元素集合,这个方法用于缩小匹配的范围,用逗号分隔多个表达式 当参数是函数时,函数里面的参数解释如下: 一个函数用来作为测试元素的集合.它接受一个参数index,这是元素在jQuery集合的索引.在函数, this指的是当前的DOM元素 实例:<!DOCTYPE html> <html lang='zh-cn'> <head> <title>Insert you title</title> <meta http-equ

ztree获取当前选中节点子节点id集合的方法(转载)

本文实例讲述了ztree获取当前选中节点子节点id集合的方法.分享给大家供大家参考.具体分析如下: 要求:获取当前选中节点的子节点id集合. 步骤: 1.获取当前节点 2.用ztree的方法transformToArray()获取当前选中节点(含选中节点)的子节点对象集合. 3.遍历集合,取出需要的值. treeNode:当前选中节点对象 function getChildNodes(treeNode) { var naviTree = $.fn.zTree.getZTreeObj(zTreeI

《Java虚拟机原理图解》1.5、 class文件中的方法表集合--method方法在class文件中是怎样组织的

0. 前言 了解JVM虚拟机原理是每一个Java程序员修炼的必经之路.但是由于JVM虚拟机中有很多的东西讲述的比较宽泛,在当前接触到的关于JVM虚拟机原理的教程或者博客中,绝大部分都是充斥的文字性的描述,很难给人以形象化的认知,看完之后感觉还是稀里糊涂的. 感于以上的种种,我打算把我在学习JVM虚拟机的过程中学到的东西,结合自己的理解,总结成<Java虚拟机原理图解> 这个系列,以图解的形式,将抽象的JVM虚拟机的知识具体化,希望能够对想了解Java虚拟机原理的的Java程序员 提供点帮助.

ios中集合遍历方法的比较和技巧

本文原文发表自我的[自建博客],cnblogs同步发表,格式未经调整,内容以原博客为准 我是前言 集合的遍历操作是开发中最常见的操作之一,从C语言经典的for循环到利用多核cpu的优势进行遍历,开发中ios有若干集合遍历方法,本文通过研究和测试比较了各个操作方法的效率和优略势,并总结几个使用集合遍历时的小技巧. ios中常用的遍历运算方法 遍历的目的是获取集合中的某个对象或执行某个操作,所以能满足这个条件的方法都可以作为备选: 经典for循环 for in (NSFastEnumeration)

java 程序语言中的LinkedList 集合基本方法演示

java 程序语言中的LinkedList 集合基本方法演示 import java.util.Iterator; import java.util.LinkedList; public class LinkedListDemos { public static void main(String[] args) { // 新建一个容器 LinkedList link = new LinkedList(); link.addFirst("abc1"); link.addFirst(&qu

黑马程序员——java基础 ArrayList集合基本方法演示

java基础 ArrayList集合基本方法演示 import java.util.ArrayList; import java.util.Iterator; public class ArrayListDemos { public static void main(String[] args) { // 创建一个新的容器 ArrayList al = new ArrayList(); al.add("abc1"); al.add("abc2"); al.add(&

遍历Map集合四中方法

<embed wmode="transparent" src="http://chabudai.sakura.ne.jp/blogparts/honehoneclock/honehone_clock_tr.swf" quality="high" bgcolor="#ffffff" width="160" height="70" name="honehoneclock&qu

Python中set集合使用方法

set是一个无序且不重复的元素集合,它有可变集合(set())和不可变集合(frozenset)两种,可以对set()集合进行创建.添加.删除.交集.并集和差集的操作,非常实用,以下是具体用法: 一.创建集合set python set类是在python的sets模块中,新的python版本可以直接创建集合,不需要导入sets模块. 具体用法: 1. set('old') 2. set('o','l','d') 二.集合添加 python 集合的添加有两种常用方法,分别是add和update,具

深入理解java集合框架之---------Arraylist集合 -----添加方法

Arraylist集合 -----添加方法 1.add(E e) 向集合中添加元素 /** * 检查数组容量是否够用 * @param minCapacity */ public void ensureCapacity(int minCapacity){ modCount++; int oldCapacity = elementData.length; if(minCapacity > oldCapacity){ Object oldData[] = elementData; int newCa