Лямбда-выражение для преобразования массива / списка строк в массив / список целых чисел

111

Поскольку в Java 8 есть мощные лямбда-выражения,

Я хотел бы написать функцию для преобразования списка / массива строк в массив / список целых чисел, чисел с плавающей запятой, двойных чисел и т. Д.

В обычном Java это было бы так же просто, как

for(String str : strList){
   intList.add(Integer.valueOf(str));
}

Но как мне добиться того же с помощью лямбда, учитывая массив строк, который нужно преобразовать в массив целых чисел.

Reddy
источник

Ответы:

128

Вы можете создать вспомогательные методы, которые будут преобразовывать список (массив) типа Tв список (массив) типа, Uиспользуя mapоперацию on stream.

//for lists
public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) {
    return from.stream().map(func).collect(Collectors.toList());
}

//for arrays
public static <T, U> U[] convertArray(T[] from, 
                                      Function<T, U> func, 
                                      IntFunction<U[]> generator) {
    return Arrays.stream(from).map(func).toArray(generator);
}

И используйте это так:

//for lists
List<String> stringList = Arrays.asList("1","2","3");
List<Integer> integerList = convertList(stringList, s -> Integer.parseInt(s));

//for arrays
String[] stringArr = {"1","2","3"};
Double[] doubleArr = convertArray(stringArr, Double::parseDouble, Double[]::new);


Обратите внимание, что s -> Integer.parseInt(s)его можно заменить на Integer::parseInt(см. Ссылки на методы )

Алексис С.
источник
5
Если вы используете Guava, вы также можете использовать Lists.transform().
Александрос
Очень хороший пример. Функция делает код более универсальным и мощным. Thks !!!
Марсело Ребусас
127
List<Integer> intList = strList.stream()
                               .map(Integer::valueOf)
                               .collect(Collectors.toList());
ZehnVon12
источник
5
Вы можете немного это объяснить?
Unheilig
1
Это преобразование списка String в поток, затем отображение / преобразование каждого элемента списка в Integer, а затем сбор в список.
hemanto
5
Это должен быть принятый ответ, поскольку суть лямбда-выражений (исходный вопрос требует лямбда-выражения) состоит в том, чтобы избежать определения новой функции. Вдобавок к этому, в этом ответе элегантно используется существующая функция Integer :: valueOf
Джонатан Бенн
31

Вспомогательные методы из принятого ответа не нужны. Потоки можно использовать с лямбда-выражениями или обычно сокращать с помощью ссылок на методы . Потоки позволяют выполнять функциональные операции. map()преобразует элементы и / collect(...)или toArray()возвращает поток обратно в массив или коллекцию.

Выступление Венката Субраманиама (видео) объясняет это лучше, чем я.

1 преобразовать List<String>вList<Integer>

List<String> l1 = Arrays.asList("1", "2", "3");
List<Integer> r1 = l1.stream().map(Integer::parseInt).collect(Collectors.toList());

// the longer full lambda version:
List<Integer> r1 = l1.stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList());

2 преобразовать List<String>вint[]

int[] r2 = l1.stream().mapToInt(Integer::parseInt).toArray();

3 преобразовать String[]вList<Integer>

String[] a1 = {"4", "5", "6"};
List<Integer> r3 = Stream.of(a1).map(Integer::parseInt).collect(Collectors.toList());

4 преобразовать String[]вint[]

int[] r4 = Stream.of(a1).mapToInt(Integer::parseInt).toArray();

5 преобразовать String[]вList<Double>

List<Double> r5 = Stream.of(a1).map(Double::parseDouble).collect(Collectors.toList());

6 (бонус) Конвертировать int[]вString[]

int[] a2 = {7, 8, 9};
String[] r6 = Arrays.stream(a2).mapToObj(Integer::toString).toArray(String[]::new);

Конечно, возможны и другие варианты.

Также см. Версию Ideone этих примеров . Можно нажать fork, а затем запустить для запуска в браузере.

Стэн Курдзил
источник
7

EDIT: как указано в комментариях, это гораздо более простая версия: Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray() таким образом мы можем пропустить все преобразование в список и из него.


Я нашел еще одно однострочное решение, но оно все еще довольно медленное (занимает примерно в 100 раз больше, чем цикл for - проверено на массиве из 6000 0)

String[] stringArray = ...
int[] out= Arrays.asList(stringArray).stream().map(Integer::parseInt).mapToInt(i->i).toArray();

Что это значит:

  1. Arrays.asList () преобразует массив в список
  2. .stream преобразует его в Stream (необходимо для выполнения карты)
  3. .map (Integer :: parseInt) преобразует все элементы в потоке в целые числа.
  4. .mapToInt (i-> i) преобразует все целые числа в целые числа (вам не нужно этого делать, если вам нужны только целые числа)
  5. .toArray () преобразует Stream обратно в массив
Дуршлаг
источник
13
Вам не нужны шаги 1 и 4:Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray()
xehpuk
3

Для списка:

List<Integer> intList 
 = stringList.stream().map(Integer::valueOf).collect(Collectors.toList());

Для массива:

int[] intArray = Arrays.stream(stringArray).mapToInt(Integer::valueOf).toArray();
Сахил Чабра
источник
2

Вы также можете использовать,

List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");

    Integer[] array = list.stream()
        .map( v -> Integer.valueOf(v))
        .toArray(Integer[]::new);
Тангавел Логанатан
источник
0

Я не нашел этого в предыдущих ответах, поэтому с Java 8 и потоками:

Преобразовать String[]в Integer[]:

Arrays.stream(stringArray).map(Integer::valueOf).toArray(Integer[]::new)
LeoLozes
источник
-1

Дополнительно - контроль отсутствия элементов в строковом массиве:

Arrays.stream(from).filter(t -> (t != null)&&!("".equals(t))).map(func).toArray(generator) 
Журов Константин
источник
-1

Я использовал maptoInt () с операцией Lambda для преобразования строки в Integer

int[] arr = Arrays.stream(stringArray).mapToInt(item -> Integer.parseInt(item)).toArray();
Глубокая Лотия
источник
-3

Arrays.toString (int []) работает для меня.

Правин Кодур
источник
Я не отвечаю на вопрос: «Как этого добиться с помощью лямбд».
Сергей Сирик