认识Arrays.asList方法

本文深入解析了Java Arrays.asList方法的工作原理,揭示了其生成的List为何不可进行添加或删除操作,并提供了如何创建可操作的List的替代方法。通过实例演示了如何使用自定义方法实现类似功能,确保了List的灵活性。
Arrays工具类提供了一些比较实用的方法,比如sort, binarySearch, fill等。其中还有一个 asList 方法,此方法能够将一个变长参数或者数组转换成List。 
但是,这个生成的List,它是固定长度的,如果对其进行add或者remove的操作,会抛出UnsupportedOperationException ,为什么会这样呢? 

带着疑问,查看一下Arrays的源码,可以得到问题的结果。 


  
Java代码   收藏代码
  1. /** 
  2.     * Returns a fixed-size list backed by the specified array.  (Changes to 
  3.     * the returned list "write through" to the array.)  This method acts 
  4.     * as bridge between array-based and collection-based APIs, in 
  5.     * combination with <tt>Collection.toArray</tt>.  The returned list is 
  6.     * serializable and implements {@link RandomAccess}. 
  7.     * 
  8.     * <p>This method also provides a convenient way to create a fixed-size 
  9.     * list initialized to contain several elements: 
  10.     * <pre> 
  11.     *     List<String> stooges = Arrays.asList("Larry", "Moe", "Curly"); 
  12.     * </pre> 
  13.     * 
  14.     * @param a the array by which the list will be backed. 
  15.     * @return a list view of the specified array. 
  16.     * @see Collection#toArray() 
  17.     */  
  18.    public static <T> List<T> asList(T... a) {  
  19. return new ArrayList<T>(a);  


方法asList返回的是new ArrayList<T>(a)。但是,这个ArrayList并不是java.util.ArrayList,它是一个Arrays类中的重新定义的内部类。 

具体的实现如下: 

Java代码   收藏代码
  1. /** 
  2.      * @serial include 
  3.      */  
  4.     private static class ArrayList<E> extends AbstractList<E>  
  5.     implements RandomAccess, java.io.Serializable  
  6.     {  
  7.         private static final long serialVersionUID = -2764017481108945198L;  
  8.     private Object[] a;  
  9.   
  10.     ArrayList(E[] array) {  
  11.             if (array==null)  
  12.                 throw new NullPointerException();  
  13.         a = array;  
  14.     }  
  15.   
  16.     public int size() {  
  17.         return a.length;  
  18.     }  
  19.   
  20.     public Object[] toArray() {  
  21.         return (Object[])a.clone();  
  22.     }  
  23.   
  24.     public E get(int index) {  
  25.         return (E)a[index];  
  26.     }  
  27.   
  28.     public E set(int index, E element) {  
  29.         Object oldValue = a[index];  
  30.         a[index] = element;  
  31.         return (E)oldValue;  
  32.     }  
  33.   
  34.         public int indexOf(Object o) {  
  35.             if (o==null) {  
  36.                 for (int i=0; i<a.length; i++)  
  37.                     if (a[i]==null)  
  38.                         return i;  
  39.             } else {  
  40.                 for (int i=0; i<a.length; i++)  
  41.                     if (o.equals(a[i]))  
  42.                         return i;  
  43.             }  
  44.             return -1;  
  45.         }  
  46.   
  47.         public boolean contains(Object o) {  
  48.             return indexOf(o) != -1;  
  49.         }  
  50.     }  


从这个内部类ArrayList的实现可以看出,它继承了类AbstractList<E>,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。 

Java代码   收藏代码
  1. public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {  
  2.     /** 
  3.      * Sole constructor.  (For invocation by subclass constructors, typically 
  4.      * implicit.) 
  5.      */  
  6.     protected AbstractList() {  
  7. }  
  8.   
  9. /** 
  10.      * Appends the specified element to the end of this List (optional 
  11.      * operation). <p> 
  12.      * 
  13.      * This implementation calls <tt>add(size(), o)</tt>.<p> 
  14.      * 
  15.      * Note that this implementation throws an 
  16.      * <tt>UnsupportedOperationException</tt> unless <tt>add(int, Object)</tt> 
  17.      * is overridden. 
  18.      * 
  19.      * @param o element to be appended to this list. 
  20.      *  
  21.      * @return <tt>true</tt> (as per the general contract of 
  22.      * <tt>Collection.add</tt>). 
  23.      *  
  24.      * @throws UnsupportedOperationException if the <tt>add</tt> method is not 
  25.      *        supported by this Set. 
  26.      *  
  27.      * @throws ClassCastException if the class of the specified element 
  28.      *        prevents it from being added to this set. 
  29.      *  
  30.      * @throws IllegalArgumentException some aspect of this element prevents 
  31.      *            it from being added to this collection. 
  32.      */  
  33.     public boolean add(E o) {  
  34.     add(size(), o);  
  35.     return true;  
  36.     }  
  37.   
  38.     /** 
  39.      * Inserts the specified element at the specified position in this list 
  40.      * (optional operation).  Shifts the element currently at that position 
  41.      * (if any) and any subsequent elements to the right (adds one to their 
  42.      * indices).<p> 
  43.      * 
  44.      * This implementation always throws an UnsupportedOperationException. 
  45.      * 
  46.      * @param index index at which the specified element is to be inserted. 
  47.      * @param element element to be inserted. 
  48.      *  
  49.      * @throws UnsupportedOperationException if the <tt>add</tt> method is not 
  50.      *        supported by this list. 
  51.      * @throws ClassCastException if the class of the specified element 
  52.      *        prevents it from being added to this list. 
  53.      * @throws IllegalArgumentException if some aspect of the specified 
  54.      *        element prevents it from being added to this list. 
  55.      * @throws IndexOutOfBoundsException index is out of range (<tt>index < 
  56.      *        0 || index > size()</tt>). 
  57.      */  
  58.     public void add(int index, E element) {  
  59.     throw new UnsupportedOperationException();  
  60.     }  
  61.   
  62.     /** 
  63.      * Removes the element at the specified position in this list (optional 
  64.      * operation).  Shifts any subsequent elements to the left (subtracts one 
  65.      * from their indices).  Returns the element that was removed from the 
  66.      * list.<p> 
  67.      * 
  68.      * This implementation always throws an 
  69.      * <tt>UnsupportedOperationException</tt>. 
  70.      * 
  71.      * @param index the index of the element to remove. 
  72.      * @return the element previously at the specified position. 
  73.      *  
  74.      * @throws UnsupportedOperationException if the <tt>remove</tt> method is 
  75.      *        not supported by this list. 
  76.      * @throws IndexOutOfBoundsException if the specified index is out of 
  77.      *        range (<tt>index < 0 || index >= size()</tt>). 
  78.      */  
  79.     public E remove(int index) {  
  80.     throw new UnsupportedOperationException();  
  81.     }  
  82.   
  83. }  


至此,为什么Arrays.asList产生的List是不可添加或者删除,否则会产生UnsupportedOperationException,就可以得到解释了。 

如果我们想把一个变长或者数据转变成List, 而且期望这个List能够进行add或者remove操作,那该怎么做呢? 

我们可以写一个类似的方法,里面直接采用java.util.ArrayList即可。 

比如: 
Java代码   收藏代码
  1. import java.util.ArrayList;  
  2. import java.util.Collections;  
  3. import java.util.List;  
  4.   
  5. public class MyArrays {  
  6.   
  7.     public static <T> List<T> asList(T... a) {  
  8.         List<T> list = new ArrayList<T>();  
  9.         Collections.addAll(list, a);  
  10.         return list;  
  11.     }  
  12. }  


测试代码如下: 
Java代码   收藏代码
  1. import java.util.ArrayList;  
  2. import java.util.Arrays;  
  3. import java.util.List;  
  4.   
  5. public class Test {  
  6.     @SuppressWarnings("unchecked")  
  7.     public static void main(String[] args) {  
  8.   
  9.         List<String> stooges = Arrays.asList("Larry""Moe""Curly");  
  10.         print(stooges);  
  11.   
  12.         List<List<String>> seasonsList = Arrays.asList(retrieveSeasonsList());  
  13.         print(seasonsList);  
  14.   
  15.         /* 
  16.          * 自己实现一个asList方法,能够添加和删除。 
  17.          */  
  18.         List<String> list = MyArrays.asList("Larry""Moe""Curly");  
  19.         list.add("Hello");  
  20.         print(list);  
  21.   
  22.     }  
  23.   
  24.     private static <T> void print(List<T> list) {  
  25.         System.out.println(list);  
  26.     }  
  27.   
  28.     private static List<String> retrieveSeasonsList() {  
  29.         List<String> seasonsList = new ArrayList<String>();  
  30.         seasonsList.add("Spring");  
  31.         seasonsList.add("Summer");  
  32.         seasonsList.add("Autumn");  
  33.         seasonsList.add("Winter");  
  34.         return seasonsList;  
  35.     }  
  36.   
  37. }  


输出结果: 

[Larry, Moe, Curly] 
[[Spring, Summer, Autumn, Winter]] 
[Larry, Moe, Curly, Hello] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值