Повторение карты<TypeA,Set> и преобразование ее в карту<TypeB,Set> в Java

#java #dictionary #hashmap #iteration

#java #словарь #hashmap #итерация

Вопрос:

У меня есть Map<String>,Set<String>> followingMap , где ключи — это имена пользователей, а значения — это наборы имен пользователей, за которыми следуют ключевые имена пользователей. Я должен создать followersMap , где в этом случае подписанные пользователи в наборах значений теперь являются ключами, а значение представляет собой набор подписчиков в соответствии с предыдущим k.

Не уверен, что это достаточно понятно, поэтому в качестве примера элемент в следующей карте будет: key="john", value=Set["robert","andrew,"amanda"].

В followersMap это было бы:

 key="robert", value=Set["john"]
key="andrew", value=Set["john"]
key="amanda", value=Set["john"]
  

Если вторым элементом в followingMap является key="alex",Set["amanda"] , это добавило бы «alex» к набору значений ключа «amanda».

Мой код должен выполнить трюк, однако при тестировании я получаю ключи, в которых заполняются все установленные значения.

Взгляните:

 Map<String,Set<String>> followerGraph = new HashMap<String,Set<String>>();
for (Map.Entry<String, Set<String>> me : followsGraph.entrySet()) {
              String key = me.getKey();
              Set<String> tmp = new LinkedHashSet<>();    
              Set<String> valueSet = me.getValue();
              for (String s : valueSet) {
                  if (followerGraph.containsKey(s)){
                      followerGraph.get(s).add(key);
                  } else {
                      tmp.add(key);
                      followerGraph.put(s, tmp);
                  }  
              }   
        }
  

Итак, это печать следующего графика:

 {aliana=[@jake, @john, @erick], alyssa=[@john, @erick], 
bbitdiddle=[@rock-smith, @john, @erick], casus=[@daniel, @jake, @john, @erick], 
david=[@dude, @john]}
  

И это печать следующего графика:

 {@daniel=[casus], @rock-smith=[bbitdiddle], @jake=[aliana, alyssa, bbitdiddle, casus, david], @dude=[david], @john=[aliana, alyssa, bbitdiddle, casus, david], @erick=[aliana, alyssa, bbitdiddle, casus, david]}
  

Как вы можете видеть, у @erick не должно быть подписчика Дэвида. Я что-то упускаю?
Извините, если мой код выглядит как беспорядок. Я всего 6 месяцев в Java, 4 часа изучаю, как повторять карту (пробовал потоки Java 8, но не уверен, как добавить туда if-else), и сейчас 6 утра, и моя жена может убить меня за то, что я не спал всю ночь : S

Комментарии:

1. Откуда берется следующий график?

2. Вы правы. Я не включил эту строку. Это вторая карта <String,Set<String>>, которая отображает последователей

Ответ №1:

Вы можете сделать что-то подобное:

     Map<String, Set<String>> followerMap = new HashMap<>();
    followingMap.forEach((name,followingSet)-> followingSet.forEach(
            follower-> followerMap.computeIfAbsent(follower, f->new HashSet<>())
                                  .add(name)));
  

followingMap.forEach обработайте все записи в следующей карте. Затем набор каждой записи обрабатывается с помощью followingSet.forEach . Элементами этого набора являются последователи, ключи новой карты. computeIfAbsent используется для размещения новой записи на карте, если она не существует, добавляя пустой набор в этом случае. После этого значение добавляется к набору, в данном случае к записи следующей карты.

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

     Map<String, Set<String>> followerMap = new HashMap<>();
    for (Entry<String, Set<String>> followingEntry : followingMap.entrySet()) {
        for (String follower : followingEntry.getValue()) {
            followerMap.computeIfAbsent(follower, s->new HashSet<>()).add(followingEntry.getKey());
        }
    }
  

Комментарии:

1. @WesleyDeKeirsmaeker Вы, вероятно, правы, вероятно, использование for циклов вместо forEach методов делает ее более читаемой

Ответ №2:

Попробуйте это.

 for (Map.Entry<String, Set<String>> me : followsGraph.entrySet()) {
    String key = me.getKey();
    // Set<String> tmp = new LinkedHashSet<>();     // MOVE THIS TO ...
    Set<String> valueSet = me.getValue();
    for (String s : valueSet) {
        if (followerGraph.containsKey(s)) {
            followerGraph.get(s).add(key);
        } else {
            Set<String> tmp = new LinkedHashSet<>();  // HERE
            tmp.add(key);
            followerGraph.put(s, tmp);
        }
    }
}
  

Ответ №3:

Попробуйте что-то вроде этого:

 Map<String, Set<String>> newFollowsGraph = new HashMap<>();
for (Map.Entry<String, Set<String>> me : followsGraph.entrySet()) {
          String key = me.getKey();  
          Set<String> valueSet = me.getValue();
          for (String s : valueSet) {
              if (newFollowerGraph.containsKey(s)){
                  newFollowerGraph.get(s).add(key);
              } else {
                  Set<String> tmp = new LinkedHashSet<>();
                  tmp.add(key)
                  newFollowerGraph.put(s, tmp);
              }  
          }   
    }
  

Проблема в том, что вы вставляете новые данные в объект, над которым выполняете итерацию.