HashMapa <Character, Integer> zrobiona za pomocą streamu ze Stringa.

0

Witam. Od niedawna uczę się strumieni i chociaż widziałem wiele przykładów konwersji na HashMapę, to cały czas mi nie wychodzi jeden. Chcę zamienić String zawierający litery alfabetu na HashMapę, która za klucz będzie przyjmowała każdą literę alfabetu, a wartością początkową będzie zero. Próbowałem tak:

String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        HashMap<Character,Integer> list = Stream.of(alphabet.chars())
                .map(String::valueOf)
                .map(i->i.charAt(0))
                .collect(Collectors.toMap(i1 -> i1,0));

Od razu kompilator mi wyłapuje, że:

no istance(s) of type variable(s) T, U exist so that integer conforms to Function <?super T ?extends U>

dla i1 ->i1 i nie mam pojęcia o co chodzi. Ktoś mógłby mi pomóc?

2

odpowiedź masz w stactrace, ale też w javadocu dla Collectors

 	toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

czyli toMap przyjmuje dwie funkcje a nie jedną, zamień na:

Collectors.toMap(i1 -> i1, i1 -> 0);
0
Kamil Żabiński napisał(a):

odpowiedź masz w stactrace, ale też w javadocu dla Collectors

 	toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)

czyli toMap przyjmuje dwie funkcje a nie jedną, zamień na:

Collectors.toMap(i1 -> i1, i1 -> 0);

Teraz wywala błąd: Incompatibile types. Required HashMap<Character, Integer>, but 'collect' is inferred to R: no instances of variable(s) K, U exist so that map <K,U> conforms to HashMap <Character, Integer>

0

bo toMap zwraca <T,K,U> Collector<T,?,Map<K,U>> czyli masz Map<Character, Integer>

0
Kamil Żabiński napisał(a):

bo toMap zwraca <T,K,U> Collector<T,?,Map<K,U>> czyli masz Map<Character, Integer>

Sorry, mógłbyś to w całości napisać, bo nie kumam. :(

0

[https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-]
sygnatura metody to:

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,
                                                    Function<? super T,? extends U> valueMapper)

a niżej w javadocu masz przykład użycia:

 Map<Student, Double> studentToGPA
         students.stream().collect(toMap(Functions.identity(),
                                         student -> computeGPA(student)));

a u Ciebie powinno być

Map<Character,Integer> list = Stream.of(alphabet.chars())
                .map(String::valueOf)
                .map(i->i.charAt(0))
                .collect(Collectors.toMap(i1 -> i1, i1 -> 0));
0
Kamil Żabiński napisał(a):

[https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-]
sygnatura metody to:

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,
                                                    Function<? super T,? extends U> valueMapper)

a niżej w javadocu masz przykład użycia:

 Map<Student, Double> studentToGPA
         students.stream().collect(toMap(Functions.identity(),
                                         student -> computeGPA(student)));

a u Ciebie powinno być

Map<Character,Integer> list = Stream.of(alphabet.chars())
                .map(String::valueOf)
                .map(i->i.charAt(0))
                .collect(Collectors.toMap(i1 -> i1, i1 -> 0));

Ok. Tylko to dalej nie działa. Po wydrukowaniu letterStat wychodzi na to, że hashmapa dalej jest pusta. Wydawało mi się, że rozłożenie Stringa metodą chars() i następnie przekształcenie tego na typ char załatwia sprawę. Po przepuszczeniu przez debuggera wydaje mi się, że tutaj muszę mieć jakiś błąd, ale nie wiem jaki. Szukałem po googlach "String to Character list" albo czegoś podobnego i na ogół pojawiało się to. :(

0

eh, a patrzyłeś w JavaDocs?
String::chars zwraca IntStream więc nie ma sensu jeszcze raz go pchać w Stream.of

0
Kamil Żabiński napisał(a):

eh, a patrzyłeś w JavaDocs?
String::chars zwraca IntStream więc nie ma sensu jeszcze raz go pchać w Stream.of

No ok. Faktycznie nie rozumiałem dokładnie o co chodzi kiedy z tego korzystałem, ale teraz nie jest lepiej, bo:

        Map<Character,Integer> list = alphabet.chars()
                .mapToObj(String::valueOf)
                .map(i->i.charAt(0))
                .collect(Collectors.toMap(i1 -> i1, i1 -> 0));

zwraca mi: Exception in thread "main" java.lang.IllegalStateException: Duplicate key 6 (attempted merging values 0 and 0) próbowałem czy aby nie powinienem zmieniać integer na Character za pomocą Character.forDigit albo po prostu i ->(char)i ale też nie działa. :(

0

Ale co Ty tam za dziwne mapowania robisz?

  • String::valueOf zamienia int na Stringa, czyli 65 (wartość znaku 'A') na "65", 66 (wartość znaku 'B') na "66" itd.
  • i->i.charAt(0) wyciąga pierwszy znam ze Stringa, czyli zamienia "65" na '6', "66" znów na '6' itd.
  • Klucze się powtarzają ('6') i masz wyjątek

Spróbuj tak:

        Map<Character,Integer> list = alphabet.chars()
                .mapToObj(i -> (char) i)
                .collect(Collectors.toMap(i1 -> i1, i1 -> 0));
0

No i teraz faktycznie nie wywala błędu, ale gdy drukuję tą hashMapę, to wychodzi, że jest pusta.

0

W sencie że ten kod Ci nie działa?

import java.util.*;
import java.util.stream.*;

public class WriteOnly {

    public static void main(String []args) {
        
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Map<Character,Integer> list = alphabet.chars()
                .mapToObj(i -> (char) i)
                .collect(Collectors.toMap(i1 -> i1, i1 -> 0));
        System.out.println(list);
    }
}

SOA1

0

O jaaa. Pardon. Wszystko gra. Dzięki bardzo. Mam jeszcze jedno pytanie. Czy dałoby radę za pomocą tego strumienia, zmienić jakąś zmienną która jest na zewnątrz? Dajmy na to mam int iterator o wartości 0 i chciałbym żeby dla każdego elementu w strumieniu wartość zwiększała się o jeden.

1

Nie do końca rozumiem. Chodzi CI o zmianę (zwiększenie) każdego elementu? Od tego jest metoda map

        IntStream
          .of(0, 1, 2, 3, 4)
          .map(i -> i + 1)
          .forEach(System.out::println);

Ok rozumiem. Masz element początkowy i chcesz generować kolejne elementy?
Jeśli to jest strumień skończony to można użyć range:

        IntStream
          .range(0, 6)
          .forEach(System.out::println);

Dla nieskończoych:

        IntStream
          .iterate(0, i -> i + 1)
          .forEach(System.out::println);
0

Mi chodziło o to, żeby za pomocą tego samego strumienia, którego używam do stworzenia HashMapy zmienić też zmienne, które do niej nie wchodzą. Coś jak:

      String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

       int iterator = 0;

       Map<Character,Integer> list = alphabet.chars()
               .mapToObj(i -> (char) i)
               .map(i->iterator++)
               .collect(Collectors.toMap(i1 -> i1, i1 -> 0));

       System.out.println(list);

   }
0

Dobrze. ( ͡° ͜ʖ ͡°)

1 użytkowników online, w tym zalogowanych: 0, gości: 1