疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

认识Arrays.asList方法


 

   Arrays工具类提供了一些比较实用的方法,比如sort, binarySearch, fill等。其中还有一个asList方法,此方法能够将一个变长参数或者数组转换成List。

  但是,这个生成的List,它是固定长度的,如果对其进行add或者remove的操作,会抛出UnsupportedOperationException,为什么会这样呢?

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

  Java代码

  /**

  * Returns a fixed-size list backed by the specified array. (Changes to

  * the returned list "write through" to the array.) This method acts

  * as bridge between array-based and collection-based APIs, in

  * combination with Collection.toArray. The returned list is

  * serializable and implements {@link RandomAccess}.

  *

  *

  This method also provides a convenient way to create a fixed-size

  * list initialized to contain several elements:

  *

  * List stooges = Arrays.asList("Larry", "Moe", "Curly");

  *

  *

  * @param a the array by which the list will be backed.

  * @return a list view of the specified array.

  * @see Collection#toArray()

  */

  public static List asList(T... a) {

  return new ArrayList(a);

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

  具体的实现如下:

  Java代码

  /**

  * @serial include

  */

  private static class ArrayList extends AbstractList

  implements RandomAccess, java.io.Serializable

  {

  private static final long serialVersionUID = -2764017481108945198L;

  private Object[] a;

  ArrayList(E[] array) {

  if (array==null)

  throw new NullPointerException();

  a = array;

  }

  public int size() {

  return a.length;

  }

  public Object[] toArray() {

  return (Object[])a.clone();

  }

  public E get(int index) {

  return (E)a[index];

  }

  public E set(int index, E element) {

  Object oldValue = a[index];

  a[index] = element;

  return (E)oldValue;

  }

  public int indexOf(Object o) {

  if (o==null) {

  for (int i=0; i

  if (a[i]==null)

  return i;

  } else {

  for (int i=0; i

  if (o.equals(a[i]))

  return i;

  }

  return -1;

  }

  public boolean contains(Object o) {

  return indexOf(o) != -1;

  }

  }

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

  Java代码

  public abstract class AbstractList extends AbstractCollection implements List {

  /**

  * Sole constructor. (For invocation by subclass constructors, typically

  * implicit.)

  */

  protected AbstractList() {

  }

  /**

  * Appends the specified element to the end of this List (optional

  * operation).

  *

  * This implementation calls add(size(), o).

  *

  * Note that this implementation throws an

  * UnsupportedOperationException unless add(int, Object)

  * is overridden.

  *

  * @param o element to be appended to this list.

  *

  * @return true (as per the general contract of

  * Collection.add).

  *

  * @throws UnsupportedOperationException if the add method is not

  * supported by this Set.

  *

  * @throws ClassCastException if the class of the specified element

  * prevents it from being added to this set.

  *

  * @throws IllegalArgumentException some aspect of this element prevents

  * it from being added to this collection.

  */

  public boolean add(E o) {

  add(size(), o);

  return true;

  }

  /**

  * Inserts the specified element at the specified position in this list

  * (optional operation). Shifts the element currently at that position

  * (if any) and any subsequent elements to the right (adds one to their

  * indices).

  *

  * This implementation always throws an UnsupportedOperationException.

  *

  * @param index index at which the specified element is to be inserted.

  * @param element element to be inserted.

  *

  * @throws UnsupportedOperationException if the add method is not

  * supported by this list.

  * @throws ClassCastException if the class of the specified element

  * prevents it from being added to this list.

  * @throws IllegalArgumentException if some aspect of the specified

  * element prevents it from being added to this list.

  * @throws IndexOutOfBoundsException index is out of range (index <

  * 0 || index > size()).

  */

  public void add(int index, E element) {

  throw new UnsupportedOperationException();

  }

  /**

  * Removes the element at the specified position in this list (optional

  * operation). Shifts any subsequent elements to the left (subtracts one

  * from their indices). Returns the element that was removed from the

  * list.

  *

  * This implementation always throws an

  * UnsupportedOperationException.

  *

  * @param index the index of the element to remove.

  * @return the element previously at the specified position.

  *

  * @throws UnsupportedOperationException if the remove method is

  * not supported by this list.

  * @throws IndexOutOfBoundsException if the specified index is out of

  * range (index < 0 || index >= size()).

  */

  public E remove(int index) {

  throw new UnsupportedOperationException();

  }

  }

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

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

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

  比如:

  Java代码

  import java.util.ArrayList;

  import java.util.Collections;

  import java.util.List;

  public class MyArrays {

  public static List asList(T... a) {

  List list = new ArrayList();

  Collections.addAll(list, a);

  return list;

  }

  }

  测试代码如下:

  Java代码

  import java.util.ArrayList;

  import java.util.Arrays;

  import java.util.List;

  public class Test {

  @SuppressWarnings("unchecked")

  public static void main(String[] args) {

  List stooges = Arrays.asList("Larry", "Moe", "Curly");

  print(stooges);

  List> seasonsList = Arrays.asList(retrieveSeasonsList());

  print(seasonsList);

  /*

  * 自己实现一个asList方法,能够添加和删除。

  */

  List list = MyArrays.asList("Larry", "Moe", "Curly");

  list.add("Hello");

  print(list);

  }

  private static void print(List list) {

  System.out.println(list);

  }

  private static List retrieveSeasonsList() {

  List seasonsList = new ArrayList();

  seasonsList.add("Spring");

  seasonsList.add("Summer");

  seasonsList.add("Autumn");

  seasonsList.add("Winter");

  return seasonsList;

  }

  }

  输出结果:

  [Larry, Moe, Curly]

  [[Spring, Summer, Autumn, Winter]]

  [Larry, Moe, Curly, Hello]