#java #arrays #lambda
Вопрос:
Есть ли какой-нибудь способ объявить и заполнить массив в Java с помощью встроенной функции / лямбда, как показано ниже?
final int NUM_NAMES = 10;
String names = () -> {
ArrayList<String> names = new ArrayList();
for (int i = 0; i < NUM_NAMES; i ) {
names.add("Name " i);
}
return names.toArray();
};
Комментарии:
1. Вы можете сделать что-то подобное, если целевой / объявленный тип лямбда-выражения является функциональным интерфейсом (а не строкой, как у вас). Чего именно вы пытаетесь достичь?
2.
IntStream.range(0, NUM_NAMES).mapToObj(i -> "Name " i).toArray(String[]::new)
.
Ответ №1:
Вы могли бы использовать следующее:
List<String> names = IntStream.range(0, 10)
.boxed()
.map(i -> String.format("Name %d", i))
.collect(Collectors.toList())
Надеюсь, синтаксис там в порядке, но вы поняли идею.
Комментарии:
1. Не нужно этого делать
boxed()
, просто делайmapToObj(...)
.2. @AndyTurner Тогда, однако, в выражении была бы автоматическая
String.format("Name %d", i)
блокировка, которую этот подход обходит. Я думаю, это компромисс.3. @Izruo на самом деле речь идет не о боксе, а скорее о том, что не нужно явно вставлять бокс. (Но вы можете избежать бокса, офк, просто выполнив прямую конкатенацию
"name " i
).
Ответ №2:
Технически вы можете сделать это встроенным, но синтаксис довольно подробный:
String[] names = ((Supplier<String[]>)() -> {
ArrayList<String> namesList = new ArrayList<>();
for (int i = 0; i < NUM_NAMES; i ) {
namesList.add("Name " i);
}
return namesList.toArray(new String[0]);
}).get();
поэтому я бы не рекомендовал это. Вам нужно будет указать тип лямбда-выражения, привести его к этому типу, а затем поместить все приведенное выражение в скобки, чтобы вы могли вызвать get
, чтобы получить созданный массив.
Более кратким способом инициализации встроенных массивов был бы вспомогательный метод, подобный этому (он вдохновлен конструкторами массивов Kotlin):
public static <T> T[] buildArray(T[] arr, IntFunction<T> elementFunction) {
for (int i = 0 ; i < arr.length ; i ) {
arr[i] = elementFunction.apply(i);
}
return arr;
}
Во втором параметре вы указываете, какой элемент вы хотите для каждого индекса:
String[] names = buildArray(new String[NUM_NAMES], i -> "Name " i);
Комментарии:
1. Ваш
buildArray
метод — это то, какArrays.setAll
он должен был быть реализован.
Ответ №3:
Возможно, самый короткий способ — использовать Arrays.setAll, который можно использовать для установки значений в массивах любого типа, а также генератор индексных значений для определения каждого индексированного значения:
String[] names = new String[NUM_NAMES];
Arrays.setAll(names, i -> "Name " i);
К сожалению Arrays.setAll
, не возвращает массив, поэтому вы не можете поместить все объявление names
в одну строку.