Я хочу создать список параметров для тестирования. Сначала я сделал это:
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
требуется довольно много ввода.
Существуют альтернативы, такие как создание анонимного внутреннего класса с инициализатором экземпляра (также называемым "инициализацией двойной скобки" ):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Тем не менее, я не слишком люблю этот метод, потому что в итоге вы являетесь подклассом ArrayList
, у которого есть инициализатор экземпляра, и этот класс создается только для создания одного объекта - это просто похоже на немного переборщить со мной.
Что было бы хорошо, если бы Предложение коллекции литералов для Project Монета была принята (предполагается, что она будет представлена на Java 7, но она вряд ли будет частью Java 8.):
List<String> list = ["A", "B", "C"];
К сожалению, это вам не поможет, поскольку оно инициализирует неизменяемый List
, а не ArrayList
, и, кроме того, он пока недоступен, если он когда-либо будет.
Было бы проще, если бы вы просто объявили его как List
- это должен быть ArrayList?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Или, если у вас есть только один элемент:
List<String> places = Collections.singletonList("Buenos Aires");
Это означало бы, что places
неизменный (при попытке изменить это вызовет исключение UnsupportedOperationException
).
Чтобы создать изменяемый список, который является конкретным ArrayList
, вы можете создать ArrayList
из неизменяемого списка:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
В Java 9 или более поздней версии:
List<String> strings = List.of("foo", "bar", "baz");
Это даст вам неизменный List
, поэтому его нельзя изменить.
Это то, что вы хотите в большинстве случаев, когда вы его предварительно заполняете.
List<String> strings = Arrays.asList("foo", "bar", "baz");
Это даст вам List
поддерживаемый массивом, поэтому он не может изменить длину.
Но вы можете вызвать List.set
, так что он все еще изменчив.
Вы можете сделать Arrays.asList
еще короче с помощью статического импорта:
List<String> strings = asList("foo", "bar", "baz");
Статический импорт:
import static java.util.Arrays.asList;
Что любая современная IDE предложит и автоматически сделает для вас.
Например, в IntelliJ IDEA вы нажимаете Alt+Enter
и выбираете Static import method...
Тем не менее, я не рекомендую List.of
Java 9 List.of
метод, потому что просто of
за of
становится путать. List.of
уже достаточно короткий и хорошо читается.
Stream
s Почему это должен быть List
?
В Java 8 или более поздней версии вы можете использовать более гибкий Stream
:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Вы можете объединить Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Или вы можете перейти из Stream
в List
:
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Но желательно просто использовать Stream
не собирая его в List
.
java.util.ArrayList
(Вы, вероятно, не.)
Процитирую JEP 269 (выделение мое):
Существует небольшой набор вариантов использования для инициализации изменяемого экземпляра коллекции с предопределенным набором значений. Обычно желательно, чтобы эти предопределенные значения были в неизменяемой коллекции, а затем инициализировать изменяемую коллекцию с помощью конструктора копирования.
Если вы хотите предварительно заполнить ArrayList
и добавить к нему впоследствии (почему?), Используйте
List<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
или в Java 8 или ранее:
List<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
или используя Stream
:
List<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Но опять же, лучше просто использовать Stream
напрямую, а не собирать его в List
.
Вы сказали, что объявили список как ArrayList
в своем коде, но делать это следует только в том случае, если вы используете какой-либо элемент ArrayList
, которого нет в List
.
Что вы, скорее всего, не делаете.
Обычно вы должны просто объявлять переменные с помощью наиболее общего интерфейса, который вы собираетесь использовать (например, Iterable
, Collection
или List
), и инициализировать их конкретной реализацией (например, ArrayList
, LinkedList
или Arrays.asList()
).
В противном случае вы ограничиваете свой код этим конкретным типом, и вам будет сложнее изменить его, когда вы захотите.
Например:
// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();
// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>();
// List if you also need .get(index):
List<String> strings = new ArrayList<>();
// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>(); // You don't need ArrayList
// Java 10 makes this moot:
var strings = new ArrayList<String>();
Другим примером будет всегда объявлять переменную InputStream
даже если это обычно FileInputStream
или BufferedInputStream
, потому что однажды вы или кто-то еще захотите использовать какой-либо другой тип InputStream
.
Arrays.asList
является статическим методом. См. Docs.oracle.com/javase/1.5.0/docs/guide/language/…
Если вам нужен простой список размером 1:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
Если вам нужен список из нескольких объектов:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
С Guava вы можете написать:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
В Гуаве есть и другие полезные статические конструкторы. Вы можете прочитать о них здесь.
java.util.Arrays
таких как, List<String> names = Arrays.asList("Beckah", "Sam", "Michael");
Литералы коллекции не попали в 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));
В Java 9
, как предложено в предложении по усовершенствованию JDK - 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")
что аналогично предложению Collection Literals, как заявлено @coobird. Также уточняется в документе JEP -
альтернативы
Языковые изменения были рассмотрены несколько раз и отклонены:
Проект монетного предложения, 29 марта 2009 г.
Проект монетного предложения, 30 марта 2009 г.
JEP 186 дискуссия по лямбда-деву, январь-март 2014
Языковые предложения были отложены в предпочтении перед библиотечным предложением, как показано в этом сообщении.
Related => В чем смысл перегруженных методов фабрики удобства для коллекций в Java 9
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"))
, который становится unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))
с статический импорт. Вам не нужны Google Коллекции для этого.
Вы можете создать фабричный метод:
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;
}
В Java 9 мы можем легко инициализировать 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"));
Этот новый подход Java 9 имеет много преимуществ по сравнению с предыдущими:
Смотрите этот пост для более подробной информации → В чем разница между List.of и Arrays.asList?
Вот еще один способ:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
С Коллекции Eclipse (ранее Коллекции GS), вы можете написать следующее:
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");
Вы также можете сделать то же самое с Sets and Bags:
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.
О самом компактном способе сделать это:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Просто используйте приведенный ниже код следующим образом.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Вы можете использовать приведенные ниже инструкции:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
letters = Arrays.asList(new String[]{"A", "B", "C"});
(Должен быть комментарий, но слишком длинный, поэтому новый ответ). Как уже упоминалось, метод Arrays.asList
имеет фиксированный размер, но это не единственная проблема с ним. Он также не очень хорошо обрабатывает наследование. Например, предположим, у вас есть следующее:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Вышеуказанное приводит к ошибке компилятора, потому что List<B>
(то, что возвращает Arrays.asList) не является подклассом List<A>
, даже если вы можете добавить объекты типа B в объект List<A>
, Чтобы обойти это, вам нужно сделать что-то вроде:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
Это, вероятно, лучший способ сделать это, особенно. если вам нужен неограниченный список или вам нужно использовать наследование.
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> 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.
Вы можете использовать StickyList
из Cactoos:
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
List<String> names = Arrays.asList("2","@2234","21","11");
Да с помощью массивов вы можете инициализировать список массивов в одной строке,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
Попробуйте использовать эту строку кода:
Collections.singletonList(provider)
В 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.
Иногда я просто чувствую, что люди просто должны использовать Groovy и пусть Java остается в покое. Хорошо, что он работает на JVM, поэтому вы можете скопировать чистый Java-код в любом месте в файле Groovy, и он будет работать.
О объявлении списка в одной строке, вот как он выглядит в Groovy:
def list1 = [1,2,3]
Что это, maan!!!
Дополнительно
Объявление карты в Groovy в одной строке:
def map1 = [key1:1,key2:2]
Чтение файла JSON,
{ "map1":{"map2":{"key":"value1"}}}
в одной строке:
String value = new JsonSlurper().parse("path\\to\\file")["map1"]["map2"]["key"]
или
String value = new JsonSlurper().parse("path\\to\\file").map1.map2.key
Оба набора value
- value1
.
Представьте, что вы делаете то же самое с Jackson API. Вы должны написать соответствующие POJOs для map1 и map2. Затем скомпилируйте. Также каждый раз, когда JSON изменяется, вы должны отражать эти изменения в POJO. Это полностью поражает цель создания функциональности JSON. Это смертельная цепочка перекомпиляции кода-кода. Не просто настроить и уйти.
Я плачу, когда меня попросили использовать Java. Почему мир почему???? (или, пожалуйста, просветите меня, если я ошибаюсь... уменьшит большую часть моей боли в Java World)
Вот код от 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");
Декларация: я разработчик AbacusUtil.
Лучший способ сделать это:
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);
}
}
Просто создайте функцию, которая может иметь столько элементов, сколько вы хотите, и вызовите ее, чтобы добавить их в одну строку.
Object
.
Collections.singletonList(messageBody)
Если вам нужно будет иметь список одного элемента!
Коллекции из пакета java.util.
Почему бы не сделать простую служебную функцию, которая делает это?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
" ll
" означает "буквальный список".
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
Для меня Arrays.asList() - лучший и удобный. Мне всегда нравится инициализировать этот путь. Если вы новичок в сборниках Java, я хотел бы, чтобы вы ссылались на ArrayList инициализацию
add()
?
Собственно, это можно сделать в одной строке:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
Это реализация Arrays.asList
, поэтому вы можете пойти с
ArrayList<String> arr = (ArrayList<String>) Arrays.asList("1", "2");
В среде Apple WebObjects Foundation вы можете сделать это.
NSArray<String> places1 = new NSArray<String>("Buenos Aires", "Córdoba", "La Plata");
NSMutableArray<String> places2 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");
List<String> places3 = new NSMutableArray<String>("Buenos Aires", "Córdoba", "La Plata");
Основа WebObjects Foundation была перенесена с Objective-C на Java более десяти лет назад и была обновлена после добавления поддержки Java для генериков... Интересно, почему что-то подобное не было реализовано в классах Java Collections.
ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]