Мультикарта может хранить только несколько значений на ключ, но вам нужно объединить эти несколько значений, чтобы получить один элемент с одинаковыми идентификатором и заголовком, а также набор ключевых слов и информации о таргетинге.Поэтому, вероятно, было бы лучше иметь что-то вроде MultiStory
или уже иметь Story
, содержащее эти коллекции.
Я бы предложил использовать правильные объекты вместо карт, но с картами и лямбдами Java 8 вы можете использовать compute()
и т. Д. Для создания карт, содержащих коллекции, и комбинировать карты, которые этого не делают.
Вот пример того, как вы делаете это с картами.Обратите внимание, что это очень плохой стиль, и пример с использованием правильных pojos будет следующим:
Отказ от ответственности: пример, основанный на коде OP, не рекомендуется (см. Текст выше)
//Problem 1: we don't know the type of the values, i.e. we could put anything for "id" etc.
Map<String, Object> story1=new HashMap<>();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");
Map<String, Object> story2=new HashMap<>();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");
List<Map<String, Object>> stories=new ArrayList<>();
stories.add(story1);
stories.add(story2);
Map<Integer, Map<String, Object>> combined = new HashMap<>();
stories.forEach((story) -> {
//Problem 2: because we don't know the type of the values we need a lot of nasty casts
Map<String, Object> combinedStory = combined.computeIfAbsent( (Integer)story.get( "id" ), k -> new HashMap<String, Object>() );
combinedStory.put("id", story.get( "id" ) );
combinedStory.put("title", story.get( "title" ) );
//Problem 3: the combined map would look a lot like your "story" maps but would contain different types
((List<String>)combinedStory.computeIfAbsent( "keyword", v -> new List<String>() )).add( (String)story.get("keyword") );
((List<String>)combinedStory.computeIfAbsent( "targeting", v -> new List<String>() )).add( (String)story.get("targeting") );
});
Использование POJO
Вот очень упрощенный пример того, как вы делаете это с правильными объектами Java (POJO).Обратите внимание, что они должны максимально напоминать ваш код, и есть много других проблем, но здесь их будет слишком много, и лучше разработанный код будет намного больше и, вероятно, труднее для понимания - в конце концов, это просто означаетчтобы показать вам разницу.
Сначала давайте определим наши классы (для простоты я сделал поля общедоступными, обычно вы этого не сделаете):
class Story {
public final int id;
public String title;
public String keyword;
public String targeting;
public Story(int storyId) {
id = storyId ;
}
}
class MultiStory {
public final int id;
public String title;
public Set<String> keywords = new HashSet<>();
public Set<String> targetingInfo = new HashSet<>();
public MultiStory( int storyId ) {
id = storyId ;
}
}
Затем давайте повторим код выше:
Story story1=new Story( 1 );
story1.title = "Onboarding";
story1.keyword = "new joinee";
story1.targeting = "finance";
Story story2=new Story( 1 );
story2.title = "Onboarding";
story2.keyword = "training";
story2.targeting = "HR";
List<Story> stories=new ArrayList<>();
stories.add(story1);
stories.add(story2);
Map<Integer, MultiStory> combined = new HashMap<>();
stories.forEach((story) -> {
MultiStory multiStory = combined.computeIfAbsent( story.id, v -> new MultiStory( story.id ) );
multiStory.title = story.title;
multiStory.keywords.add( story.keyword );
multiStory.targetingInfo.add( story.targeting );
});
Как видите, нет необходимости в преобразованиях, и ясно, какие поля доступны (хотя и не обязательно заполнены), что упрощает анализ кода и обнаружение ошибок (компилятор может помочьмного чего здесь не получилось в примере, использующем карты).