Arrays.asList()方法注意

(1)   asList()方法注意---返回一个定长的list


import java.util.Arrays;  
import java.util.List;  
  
  
public class TestAsList {  
  
    public static void main(String[] args) {  
        String[] str = new String[]{"1","2","3"};  
        List list = Arrays.asList(str);  
        list.add("4");  
    }  
}  

运行程序,报以后错误:


Exception in thread "main" java.lang.UnsupportedOperationException  
    at java.util.AbstractList.add(AbstractList.java:131)  
    at java.util.AbstractList.add(AbstractList.java:91)  
    at test.TestAsList.main(TestAsList.java:12)  

分析原因:

     

   public void add(int index, Object element) {
          
             throw new UnsupportedOperationException();
        }
          所以就报UnsupportedOperationException了

      这个问题是因为Arrays.ArrayList而不是java.util.ArrayList. 而Arrays.ArrayList里面没有实现add方法,是继承的AbstractList.

      当调用add方法的时候,会去调用AbstractList的add方法,而AbstractList里面的add方法是如下的:

     

解决办法如下:

Java代码 
import java.util.ArrayList;  
import java.util.Arrays;  
import java.util.List;  
  
  
public class TestAsList {  
  
    public static void main(String[] args) {  
        String[] str = new String[]{"1","2","3"};  
        List list = new ArrayList(Arrays.asList(str));  

// 方法一:利用ArrayList的构造函数:public ArrayList(Collection c)
ArrayList lt = new ArrayList(Arrays.asList(str));

//方法二:先建一个ArrayList,利用ArrayList的public boolean addAll(Collection c)   
        ArrayList lt = new ArrayList();
        lt.addAll(Arrays.asList(str));

        list.add("4");  
        System.out.println(list.size());  
    }  
}  

(2 ) asList()方法注意----基本类型,用包装类型来实现

   

 代码如下: 


Java代码   收藏代码
  1. public static void main(String[] args) {  
  2.         int[] data = {1,2,3,4,5};  
  3.         List list = Arrays.asList(data);  
  4.         System.out.println("列表中的元素数量是:" + list.size());  
  5.     }  

        注意这里输出的数量是1,原因是,在Arrays.asList中,其接收的参数原型其实是泛型变长参数来的,而基本类型是不能作为范型的参数   按道理应该使用包装类型,但这里缺没有报错,  因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组 
 
Java代码   收藏代码
  1. int[] data = {1,2,3,4,5};  
  2.         List list = Arrays.asList(data);  
  3.         System.out.println("元素类型:" + list.get(0).getClass());  
  4.         System.out.println("前后是否相等:"+data.equals(list.get(0)));  

   可以看到,输出的为元素类型:class [I  
  因为jvm不可能输出array类型,array类型属于java.lang.reflect包,通过反射访问  数组的这个类,编译时候生成的。所以要改为: 
  
Java代码   收藏代码
  1.     Integer[] data = {1,2,3,4,5};  
  2.     List list = Arrays.asList(data);  
  3.     System.out.println("列表中的元素数量是:" + list.size());  
 



总结:


    1    对于Arrays.asList()方法返回的List,不能直接再添加元素。 只能新建一个list来保存asList的返回结果,如果想做插入的话。


          利用Arrays.asList(array)将返回一个List,然而这个返回的List并不支持add和remove的操作



    2   对于包装类型与基本类型,传递aslist方法的参数时,需要传递包装类型的数组。



(3 )  List中的删除元素注意

                  对于Collection集合动态地删除元素,不能使用for --each循环来实现,应使用迭代器 或者 在传统的for循环下,自己维护一个索引。


1  自己维护索引实现        

    for(int i = 0; i < intList.size(); i++) {
           Integer value = intList.get(i);
           if(value == 3 || value == 5) {
              intList.remove(i);
              i--; 
           }    
       }

2 迭代器实现

     Iterator it = intList.iterator();
       while(it.hasNext()) {
           Integer value = it.next();
           if(value == 3 || value == 5) {
              it.remove();
           }
       }

3 常见错误:

  1增强型for循环删除元素出错 
             
   for (int t : b) {
if (lt.contains(t)) {
    lt.remove(t);
}


 2 传统for循环删除元素出错,解决方法见上面的二级标题 1 

(4 )  慎用ArrayList的contains方法,使用HashSet的contains方法代替

            ArrayList的contains方法的源码,发现其最终会调用他本身的indexOf方法

[java]  view plain copy
  1. public int indexOf(Object elem) {  
  2.     if (elem == null) {  
  3.         for (int i = 0; i < size; i++)  
  4.         if (elementData[i]==null)  
  5.             return i;  
  6.     } else {  
  7.         for (int i = 0; i < size; i++)  
  8.         if (elem.equals(elementData[i]))  
  9.             return i;  
  10.     }  
  11.     return -1;  
  12.     }  
原来在这里他做的是遍历整个list进行查找,最多可能对一个键的查找会达到6万多次,也就是会扫描整个List,验怪会这么慢了。

     于是将原来的List替换为Set:

[java]  view plain copy
  1. Set uniqueKeySet = new HashSet();  
  2. //......  
  3. if (uniqueKeySet.contains(uniqueKey)) {  
  4.                     continue;  
  5.                 }  
速度一下就上去了,在去重这一块最多花费了一秒钟,为什么HashSet的速度一下就上去了,那是因为其内部使用的是Hashtable,这是HashSet的contains的源码:

[java]  view plain copy
  1. public boolean contains(Object o) {  
  2.     return map.containsKey(o);     // hashcode  o(1)
  3.     }  
如果不知道为什么使用Hash就变快了,可以看一下我的另外一篇文章: Java中hashCode的作用




  参考:http://bo-hai.iteye.com/blog/1261566

             http://jackyrong.iteye.com/blog/1744081

             http://blog.csdn.net/fenglibing/article/details/9021201

                    

你可能感兴趣的:(Java基础)