Wyrażenie lambda do konwersji tablicy / listy ciągów na tablicę / listę liczb całkowitych

111

Ponieważ Java 8 zawiera potężne wyrażenia lambda,

Chciałbym napisać funkcję do konwersji listy / tablicy ciągów na tablicę / listę liczb całkowitych, zmiennoprzecinkowych, podwójnych itp.

W normalnej Javie byłoby to tak proste, jak

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

Ale jak osiągnąć to samo z lambdą, biorąc pod uwagę tablicę ciągów do konwersji na tablicę liczb całkowitych.

Reddy
źródło

Odpowiedzi:

128

Można utworzyć metody pomocnicze, które konwertują listę (tablicę) typu Tna listę (tablicę) typu Uprzy użyciu mapoperacji 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);
}

I użyj tego w ten sposób:

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


Należy pamiętać, że s -> Integer.parseInt(s)można je zastąpić Integer::parseInt(patrz Odnośniki do metod )

Alexis C.
źródło
5
Jeśli używasz guawy, możesz również użyć Lists.transform().
Alexandros
Bardzo dobry przykład. Funkcja sprawia, że ​​kod jest bardziej wszechstronny i potężny. Dzięki !!!
Marcelo Rebouças,
127
List<Integer> intList = strList.stream()
                               .map(Integer::valueOf)
                               .collect(Collectors.toList());
ZehnVon12
źródło
5
Czy możesz to trochę wyjaśnić?
Unheilig
1
To jest konwersja listy String na strumień, a następnie mapowanie / konwersja każdego elementu listy na liczbę całkowitą, a następnie zbieranie w listę.
hemanto
5
Powinna to być akceptowana odpowiedź, ponieważ celem lambd (pierwotne pytanie dotyczy wyrażenia lambda) jest uniknięcie definiowania nowej funkcji. Ponadto ta odpowiedź elegancko wykorzystuje istniejącą funkcję Integer :: valueOf
Jonathan Benn
31

Metody pomocnicze z zaakceptowanej odpowiedzi nie są potrzebne. Strumienie mogą być używane z lambdami lub zwykle skracane za pomocą odniesień do metod . Strumienie umożliwiają działanie funkcjonalne. map()konwertuje elementy i / collect(...)lub toArray()zawija strumień z powrotem w tablicę lub kolekcję.

Przemówienie Venkata Subramaniama (wideo) wyjaśnia to lepiej niż ja.

1 Konwertuj List<String>naList<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 Konwertuj List<String>naint[]

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

3 Konwertuj String[]naList<Integer>

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

4 Konwertuj String[]naint[]

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

5 Konwertuj String[]naList<Double>

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

6 (bonus) Zamień int[]naString[]

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

Oczywiście możliwych jest dużo więcej wariacji.

Zobacz także wersję Ideone tych przykładów . Może kliknąć widelec, a następnie uruchomić, aby uruchomić w przeglądarce.

Stan Kurdziel
źródło
7

EDYCJA: Jak wskazano w komentarzach, jest to znacznie prostsza wersja: w Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray() ten sposób możemy pominąć całą konwersję do iz listy.


Znalazłem inne rozwiązanie z jedną linią, ale nadal jest dość powolne (trwa około 100 razy dłużej niż cykl - testowane na tablicy 6000 0)

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

Co to oznacza:

  1. Arrays.asList () konwertuje tablicę na Listę
  2. .stream konwertuje go na strumień (potrzebny do wykonania mapy)
  3. .map (Integer :: parseInt) konwertuje wszystkie elementy w strumieniu na liczby całkowite
  4. .mapToInt (i-> i) konwertuje wszystkie liczby całkowite na liczby całkowite (nie musisz tego robić, jeśli chcesz tylko liczby całkowite)
  5. .toArray () konwertuje strumień z powrotem na tablicę
Durszlak
źródło
13
Nie potrzebujesz kroków 1 i 4:Arrays.stream(stringArray).mapToInt(Integer::parseInt).toArray()
xehpuk
3

Lista:

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

Dla tablicy:

int[] intArray = Arrays.stream(stringArray).mapToInt(Integer::valueOf).toArray();
Sahil Chhabra
źródło
2

Możesz także użyć,

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);
Thangavel Loganathan
źródło
0

Nie znalazłem tego w poprzednich odpowiedziach, więc z Javą 8 i strumieniami:

Konwertuj String[]na Integer[]:

Arrays.stream(stringArray).map(Integer::valueOf).toArray(Integer[]::new)
LeoLozes
źródło
-1

Dodatkowo - kontroluj, gdy tablica stringów nie zawiera elementów:

Arrays.stream(from).filter(t -> (t != null)&&!("".equals(t))).map(func).toArray(generator) 
Zhurov Konstantin
źródło
-1

Użyłem maptoInt () z operacją Lambda do konwersji stringa na Integer

int[] arr = Arrays.stream(stringArray).mapToInt(item -> Integer.parseInt(item)).toArray();
Głęboka Lotia
źródło
-3

Arrays.toString (int []) działa dla mnie.

Praveen Codur
źródło
Nie odpowiadam na pytanie: „Jak to osiągnąć z lambdami”.
Siergiej Sirik