Вираз лямбда для перетворення масиву / Список рядків у масив / Список цілих чисел


111

Оскільки Java 8 має потужні лямбда-вирази,

Я хотів би написати функцію для перетворення списку / масиву рядків у масив / список цілих чисел, плавців, парних і т.д.

У звичайній Java це було б так просто

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

Але як я досягти того ж за допомогою лямбда, задавши масив Strings для перетворення в масив Integers.

Відповіді:


128

Ви можете створити допоміжні методи, які перетворили б список (масив) типу Tв список (масив) типу, Uвикористовуючи mapоперацію на 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().
Олександрос

Дуже хороший приклад. Функція перетворює код більш універсальним і потужним. Думає !!!
Marcelo

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

5
Чи можете ви це трохи пояснити?
Unheilig

1
Це перетворення списку String у потік, а потім відображення / перетворення кожного елемента списку в Integer, а потім збирання у список.
геманто

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 версію цих прикладів . Можна натиснути вилку, а потім запустити для запуску у браузері.


7

EDIT: Як зазначалося в коментарях, це набагато простіша версія: Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray() Таким чином ми можемо пропустити всю конверсію до списку та з нього.


Я знайшов ще одне лінійне рішення, але воно все ще досить повільне (займає приблизно 100 разів довше, ніж цикл - тестується на масиві 6000 0)

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

Що це робить:

  1. Arrays.asList () перетворює масив у Список
  2. .stream перетворює його в Потік (необхідний для створення карти)
  3. .map (Integer :: parseInt) перетворює всі елементи в потоці в Цілі
  4. .mapToInt (i-> i) перетворює всі цілі особи в ints (не потрібно робити цього, якщо ви хочете лише цілі особи)
  5. .toArray () перетворює Потік назад у масив

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)

-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();

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.