-
05-07-2019 - |
题
我想创建一个选项列表进行测试的目的。第一,我这样做:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
然后,我重构的代码如下:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
有没有更好的方式做到这一点?
解决方案
实际上,可能是<!>“最好的<!>”;初始化ArrayList
的方法是你编写的方法,因为它不需要以任何方式创建新的List
:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
问题在于,引用该list
实例需要进行相当多的输入。
还有其他选择,例如使用实例初始化程序创建匿名内部类(也称为<!> quot;双括号初始化<!>;):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
但是,我不太喜欢那种方法,因为你最终得到的是<=>的子类,它有一个实例初始化器,并且创建该类只是为了创建一个对象 - 这看起来像是一个对我来说有点矫枉过正。
如果收集文字,那会更好项目硬币的提案已被接受(预计将在Java 7中引入,但它也不可能成为Java 8的一部分。):
List<String> list = ["A", "B", "C"];
不幸的是,它不会对你有帮助,因为它会初始化一个不可变的<=>而不是<=>,而且,它还没有,如果有的话。
其他提示
如果你只是将它声明为List
那么它会更简单吗?它必须是一个ArrayList吗?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
或者如果你只有一个元素:
List<String> places = Collections.singletonList("Buenos Aires");
这意味着places
不可变(尝试更改它会导致抛出UnsupportedOperationException
异常)。
要创建一个具体的ArrayList
可变列表,您可以从不可变列表中创建<=>:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
简单的答案
在Java 10,11,12或更高版本中:
var strings = List.of("foo", "bar", "baz");
在Java 9或更高版本中:
List<String> strings = List.of("foo", "bar", "baz");
这将为您提供不可变的List
,因此无法更改。
在您预先填充它的大多数情况下,这是您想要的。
Java 8或更早版本:
List<String> strings = Arrays.asList("foo", "bar", "baz");
这将为您提供由数组支持的List.set
,因此无法更改长度。
但是你可以打电话给Arrays.asList
,所以它仍然是可变的。
您可以使用静态导入使Alt+Enter
更短:
List<String> strings = asList("foo", "bar", "baz");
静态导入:
import static java.util.Arrays.asList;
任何现代IDE都会建议并自动为您做。
例如,在IntelliJ IDEA中,按Static import method...
并选择List.of
。
但是,我不建议缩短Java 9 of
方法,因为只有Stream
会让人感到困惑。
java.util.ArrayList
已经足够短,读得很好。
使用ArrayList
s
为什么必须是Iterable
?
使用Java 8或更高版本,您可以使用更灵活的Collection
:
Stream<String> strings = Stream.of("foo", "bar", "baz");
您可以连接LinkedList
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
或者您可以从Arrays.asList()
转到void method(...)
:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
但最好只使用InputStream
而不将其收集到FileInputStream
。
如果确实特别需要BufferedInputStream
(你可能没有。)
引用 JEP 269 (强调我的):
用于初始化具有预定义值集的可变集合实例的小集用例。通常最好将这些预定义值放在不可变集合中,然后通过复制构造函数初始化可变集合。
如果您希望两者预先填充<=> 并之后添加(为什么?),请使用
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
或Java 8或更早版本:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
或使用<=>:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
但同样,最好直接使用<=>而不是将其收集到<=>。
编程到接口,而不是实现
你说你已经在你的代码中将列表声明为<=>,但是如果你使用的某些<=>成员不在<=>中,你应该这样做。
你很可能不会这样做。
通常你应该通过你将要使用的最通用的接口来声明变量(例如<=>,<=>或<=>),并使用特定的实现来初始化它们(例如<=>,< =>或<=>)。
否则,您将代码限制为特定类型,并且在您想要的时候更难更改。
例如,如果您将<=>传递给<=>:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
另一个例子是总是声明变量<=>,即使它通常是<=>或<=>,因为有一天你或其他人会想要使用其他类型的<=>。
如果您需要一个大小为1的简单列表:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
如果您需要多个对象的列表:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Collection literals没有进入Java 8,但是可以使用Stream API在一个相当长的行中初始化列表:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
如果您需要确保List
是ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
使用Java 9
,如 JDK Enhancement Proposal - 269 中所述,这可能是现在使用集合文字实现 -
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
同样类似的方法也适用于Map
-
Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")
类似于收集文字提案如@coobird所述。在JEP文件中进一步澄清 -
<强>替代强>
语言变更已被多次考虑,并被拒绝:
JEP 186讨论lambda-dev,1月 - 2014年3月
语言 提议被搁置,而不是基于图书馆的提案 在此消息中进行了总结。
Related = <!> gt; 什么是Java 9中收集的便捷工厂方法的重载点
您可以创建工厂方法:
public static ArrayList<String> createArrayList(String ... elements) {
ArrayList<String> list = new ArrayList<String>();
for (String element : elements) {
list.add(element);
}
return list;
}
....
ArrayList<String> places = createArrayList(
"São Paulo", "Rio de Janeiro", "Brasília");
但它并不比你的第一次重构好得多。
为了获得更大的灵活性,它可以是通用的:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
在Java9我们可以很容易地将其初始化 ArrayList
在一个单一的线:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
或
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
这一新方法的Java9具有许多优点,比前的人:
看到这个职位的更多详细信息-> 之间的区别是什么名单。和阵列。asList?
使用 Eclipse Collections ,您可以写下以下内容:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
您还可以更具体地了解类型以及它们是可变的还是不可变的。
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
你也可以用套装和包包做同样的事情:
Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");
注意:我是Eclipse Collections的提交者。
关于最简洁的方法是:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
这是另一种方式:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
只需使用以下代码,如下所示。
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
您可以使用以下声明:
代码段:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
(应该是评论,但是太长了,所以新回复)。正如其他人所提到的,Arrays.asList
方法是固定大小的,但这并不是唯一的问题。它也不能很好地处理继承。例如,假设您有以下内容:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
上面导致编译器错误,因为List<B>
(这是Arrays.asList返回的内容)不是List<A>
的子类,即使你可以将类型B的对象添加到<=>对象。要解决这个问题,您需要执行以下操作:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
这可能是最好的方法,特别是。如果你需要一个无界的列表或需要使用继承。
像汤姆所说的那样:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
但是既然你抱怨想要一个ArrayList,你首先应该知道ArrayList是List的子类,你可以简单地添加这一行:
ArrayList<String> myPlaces = new ArrayList(places);
虽然,这可能会让你抱怨'表现'。
在这种情况下,对我来说没有意义,为什么,因为你的列表是预定义的,它没有被定义为一个数组(因为在初始化时已知大小)。如果这是你的选择:
String[] places = {"Buenos Aires", "Córdoba", "La Plata"};
如果您不关心次要的性能差异,那么您也可以非常简单地将数组复制到ArrayList:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
好的,但是将来你需要的不仅仅是地名,还需要国家代码。假设这仍然是一个在运行时永远不会改变的预定义列表,那么使用enum
集合是合适的,如果将来需要更改列表,则需要重新编译。
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
会变成:
enum Places {
BUENOS_AIRES("Buenos Aires",123),
CORDOBA("Córdoba",456),
LA_PLATA("La Plata",789);
String name;
int code;
Places(String name, int code) {
this.name=name;
this.code=code;
}
}
Enum有一个静态values
方法,它按照声明的顺序返回一个包含枚举值的所有数组,例如:
for (Places p:Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
在这种情况下,我猜你不需要你的ArrayList。
P.S。 Randyaa演示另一种使用静态实用程序方法的好方法 Collections.addAll 。
Java 9具有以下创建不可变列表的方法:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
如果需要,很容易适应创建一个可变列表:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
类似的方法可用于Set
和Map
。
List<String> names = Arrays.asList("2","@2234","21","11");
您可以使用 Cactoos 中的StickyList
:
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
尝试使用此代码行:
Collections.singletonList(provider)
是的,在数组的帮助下,你可以在一行中初始化数组列表,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
在Java中,你无法做到
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
正如所指出的,你需要进行双括号初始化:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
但这可能会迫使您添加注释@SuppressWarnings("serial")
或生成令人讨厌的串行UUID。此外,大多数代码格式化程序都会将其解包为多个语句/行。
或者你可以做
List<String> places = Arrays.asList(new String[] {"x", "y" });
但是你可能想要做一个@SuppressWarnings("unchecked")
。
同样根据javadoc你应该能够做到这一点:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
但是我无法用JDK 1.6编译它。
Collections.singletonList(messageBody)
如果您需要列出一个项目!
集合来自 java.util 包。
最好的方法:
package main_package;
import java.util.ArrayList;
public class Stackkkk {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
add(list, "1", "2", "3", "4", "5", "6");
System.out.println("I added " + list.size() + " element in one line");
}
public static void add(ArrayList<Object> list,Object...objects){
for(Object object:objects)
list.add(object);
}
}
只需创建一个可以包含任意数量元素的函数,并调用它将它们添加到一行中。
以下是 AbacusUtil 的代码
// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// The most efficient way, which is similar with Arrays.asList(...) in JDK.
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");
宣言#65306 <!>;我是AbacusUtil的开发者。
对我来说,Arrays.asList()是最好的和最方便的。我总是喜欢这样初始化。 如果您是Java Collections的初学者,那么我希望您参考 ArrayList初始化
为什么不制作一个简单的实用功能呢?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
QUOT <!>; <!> ll
QUOT;代表<!>“;文字列表<!>”;
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
我正在从存储在静态上下文中的路径之前的xml文件中创建messageTemplate列表
public final class TemplateStore {
private TemplateStore(){}
private static final String [] VERSIONS = {"081"};
private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
private static final String ERROR = "Error In Building Edifact Message Template Store";
public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
.map(version -> TemplateStore.class
.getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
.map(inputStream -> {
try {
return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
.unmarshal(inputStream)).getMessageTemplate();
} catch (JAXBException e) {
throw new IllegalArgumentException(ERROR, e);
}})
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
实际上,可以在一行中完成:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})