【发布时间】:2011-02-15 04:51:22
【问题描述】:
我知道您可以在实例化期间初始化数组,如下所示:
String[] names = new String[] {"Ryan", "Julie", "Bob"};
有没有办法用 ArrayList 做同样的事情?还是必须用array.add()单独添加内容?
【问题讨论】:
标签: java arrays initialization arraylist
我知道您可以在实例化期间初始化数组,如下所示:
String[] names = new String[] {"Ryan", "Julie", "Bob"};
有没有办法用 ArrayList 做同样的事情?还是必须用array.add()单独添加内容?
【问题讨论】:
标签: java arrays initialization arraylist
是的。
new ArrayList<String>(){{
add("A");
add("B");
}}
这实际上是在创建一个派生自ArrayList<String> 的类(外部大括号执行此操作),然后声明一个静态初始化程序(内部大括号集)。这实际上是包含类的 inner 类,因此它会有一个隐含的this 指针。除非您想对其进行序列化,或者您希望外部类被垃圾回收,否则这不是问题。
我知道 Java 7 将提供 additional language constructs 来精确地做你想做的事。
编辑:最近的 Java 版本为创建此类集合提供了更多可用的功能,并且值得对上述内容进行研究(在这些版本之前的时间提供)
【讨论】:
Arrays.asList("Ryan", "Julie", "Bob");
【讨论】:
选择的答案是:ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
但是,重要的是要了解所选答案在创建最终数组之前在内部多次复制元素,并且有一种方法可以减少一些冗余。
让我们从了解发生了什么开始:
首先,将元素复制到静态工厂Arrays.asList(T...)创建的Arrays.ArrayList<T>中。
这不会产生与java.lang.ArrayList相同的类,尽管具有相同的简单类名。尽管有一个 List 接口,但它没有实现像 remove(int) 这样的方法。如果你调用这些方法,它会抛出一个UnspportedMethodException。但如果你只需要一个固定大小的列表,你可以在这里停下来。
接下来,在#1 中构造的Arrays.ArrayList<T> 被传递给构造函数ArrayList<>(Collection<T>),在该构造函数中调用collection.toArray() 方法来克隆它。
public ArrayList(Collection<? extends E> collection) {
......
Object[] a = collection.toArray();
}
接下来构造函数决定是采用克隆的数组,还是再次复制它以删除子类类型。由于Arrays.asList(T...) 内部使用了一个类型为 T 的数组,与我们作为参数传递的相同,因此构造函数总是拒绝使用克隆,除非 T 是纯对象。 (例如,String、Integer 等都被再次复制,因为它们扩展了 Object)。
if (a.getClass() != Object[].class) {
//Arrays.asList(T...) is always true here
//when T subclasses object
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
因此,我们的数据被复制了 3 次,只是为了显式初始化 ArrayList。如果我们强制 Arrays.AsList(T...) 构造一个 Object[] 数组,我们可以将它降低到 2x,以便 ArrayList 以后可以采用它,可以这样做:
(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));
或者也许只是在创建之后添加元素可能仍然是最有效的。
【讨论】:
这个怎么样。
ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
【讨论】:
这是使用op4j Java 库(1.1. 于 2010 年 12 月发布)的流畅接口完成的:-
List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();
这是一个非常酷的库,可为您节省大量时间。
【讨论】:
这是你能得到的最接近的:
ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));
你可以更简单:
List<String> list = Arrays.asList("Ryan", "Julie", "Bob")
查看 Arrays.asList 的源代码,它构造了一个 ArrayList,但默认情况下被强制转换为 List。所以你可以这样做(但对于新的 JDK 并不可靠):
ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
【讨论】:
Arrays.asList 可以在这里提供帮助:
new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
【讨论】:
ArrayList,否则最好只使用Arrays#asList 返回的List。
Arrays.asList() 返回一个 unmodifiable 集合。 :)
Arrays.asList() 返回的列表NOT 不可修改,@kocko。它具有固定大小,但您可以更改引用以指向完全不同的对象,例如Arrays.asList(...).set(0,new String("new string")) 此代码将起作用并将列表的第一个元素设置为值为“新字符串”的字符串对象。事实上,它会直接写入本机数组!绝对不是不可修改的。
嗯,在 Java 中,列表没有文字语法,所以你必须使用 .add()。
如果你有很多元素,这有点冗长,但你可以:
2 看起来像:
String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));
这会导致一些不必要的对象创建。
【讨论】: