How to collect properties of List by unique property using MultiMap?












2















I have List of stories. Using unique property(id) I want to collect keyword and targeting as list of values. Can I do this with MultiMap? Or is there other library for this?



[{
id = 1,
title = Onboarding,
keyword = new joinee,
targeting = finance
}, {
id = 1,
title = Onboarding,
keyword = training,
targeting = HR
}]


The Desired output must like this :



{
id = 1,
title = Onboarding,
keyword = [new joinee,training], //may be keywords - plural
targeting = [HR,finance]
}


Sample my tried Code as follows:



package prac;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JavaPrac {
public static void main(String args) {
Multimap<Integer, Map> multiMap = ArrayListMultimap.create();

List<Map> stories=new ArrayList();

Map story1=new HashMap();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");

Map story2=new HashMap();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");

stories.add(story1);
stories.add(story2);

System.out.println(stories);

stories.forEach((story) -> {
multiMap.put((Integer) story.get("id"), story);
});
}
}









share|improve this question

























  • Do you want a solution for this specific mapping, or a general solution for this type of problem?

    – Adriaan Koster
    Nov 21 '18 at 9:24











  • @AdriaanKoster I did this core java program. But i want to see any libraries can help for this

    – Hearaman
    Nov 21 '18 at 9:25











  • Which title would you display if stories with the same id have different titles?

    – Adriaan Koster
    Nov 21 '18 at 9:50











  • @AdriaanKoster title is unique for an ID

    – Hearaman
    Nov 21 '18 at 9:52
















2















I have List of stories. Using unique property(id) I want to collect keyword and targeting as list of values. Can I do this with MultiMap? Or is there other library for this?



[{
id = 1,
title = Onboarding,
keyword = new joinee,
targeting = finance
}, {
id = 1,
title = Onboarding,
keyword = training,
targeting = HR
}]


The Desired output must like this :



{
id = 1,
title = Onboarding,
keyword = [new joinee,training], //may be keywords - plural
targeting = [HR,finance]
}


Sample my tried Code as follows:



package prac;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JavaPrac {
public static void main(String args) {
Multimap<Integer, Map> multiMap = ArrayListMultimap.create();

List<Map> stories=new ArrayList();

Map story1=new HashMap();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");

Map story2=new HashMap();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");

stories.add(story1);
stories.add(story2);

System.out.println(stories);

stories.forEach((story) -> {
multiMap.put((Integer) story.get("id"), story);
});
}
}









share|improve this question

























  • Do you want a solution for this specific mapping, or a general solution for this type of problem?

    – Adriaan Koster
    Nov 21 '18 at 9:24











  • @AdriaanKoster I did this core java program. But i want to see any libraries can help for this

    – Hearaman
    Nov 21 '18 at 9:25











  • Which title would you display if stories with the same id have different titles?

    – Adriaan Koster
    Nov 21 '18 at 9:50











  • @AdriaanKoster title is unique for an ID

    – Hearaman
    Nov 21 '18 at 9:52














2












2








2








I have List of stories. Using unique property(id) I want to collect keyword and targeting as list of values. Can I do this with MultiMap? Or is there other library for this?



[{
id = 1,
title = Onboarding,
keyword = new joinee,
targeting = finance
}, {
id = 1,
title = Onboarding,
keyword = training,
targeting = HR
}]


The Desired output must like this :



{
id = 1,
title = Onboarding,
keyword = [new joinee,training], //may be keywords - plural
targeting = [HR,finance]
}


Sample my tried Code as follows:



package prac;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JavaPrac {
public static void main(String args) {
Multimap<Integer, Map> multiMap = ArrayListMultimap.create();

List<Map> stories=new ArrayList();

Map story1=new HashMap();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");

Map story2=new HashMap();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");

stories.add(story1);
stories.add(story2);

System.out.println(stories);

stories.forEach((story) -> {
multiMap.put((Integer) story.get("id"), story);
});
}
}









share|improve this question
















I have List of stories. Using unique property(id) I want to collect keyword and targeting as list of values. Can I do this with MultiMap? Or is there other library for this?



[{
id = 1,
title = Onboarding,
keyword = new joinee,
targeting = finance
}, {
id = 1,
title = Onboarding,
keyword = training,
targeting = HR
}]


The Desired output must like this :



{
id = 1,
title = Onboarding,
keyword = [new joinee,training], //may be keywords - plural
targeting = [HR,finance]
}


Sample my tried Code as follows:



package prac;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JavaPrac {
public static void main(String args) {
Multimap<Integer, Map> multiMap = ArrayListMultimap.create();

List<Map> stories=new ArrayList();

Map story1=new HashMap();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");

Map story2=new HashMap();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");

stories.add(story1);
stories.add(story2);

System.out.println(stories);

stories.forEach((story) -> {
multiMap.put((Integer) story.get("id"), story);
});
}
}






java list






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 10:59









lospejos

1,47621426




1,47621426










asked Nov 21 '18 at 9:19









HearamanHearaman

4,845103048




4,845103048













  • Do you want a solution for this specific mapping, or a general solution for this type of problem?

    – Adriaan Koster
    Nov 21 '18 at 9:24











  • @AdriaanKoster I did this core java program. But i want to see any libraries can help for this

    – Hearaman
    Nov 21 '18 at 9:25











  • Which title would you display if stories with the same id have different titles?

    – Adriaan Koster
    Nov 21 '18 at 9:50











  • @AdriaanKoster title is unique for an ID

    – Hearaman
    Nov 21 '18 at 9:52



















  • Do you want a solution for this specific mapping, or a general solution for this type of problem?

    – Adriaan Koster
    Nov 21 '18 at 9:24











  • @AdriaanKoster I did this core java program. But i want to see any libraries can help for this

    – Hearaman
    Nov 21 '18 at 9:25











  • Which title would you display if stories with the same id have different titles?

    – Adriaan Koster
    Nov 21 '18 at 9:50











  • @AdriaanKoster title is unique for an ID

    – Hearaman
    Nov 21 '18 at 9:52

















Do you want a solution for this specific mapping, or a general solution for this type of problem?

– Adriaan Koster
Nov 21 '18 at 9:24





Do you want a solution for this specific mapping, or a general solution for this type of problem?

– Adriaan Koster
Nov 21 '18 at 9:24













@AdriaanKoster I did this core java program. But i want to see any libraries can help for this

– Hearaman
Nov 21 '18 at 9:25





@AdriaanKoster I did this core java program. But i want to see any libraries can help for this

– Hearaman
Nov 21 '18 at 9:25













Which title would you display if stories with the same id have different titles?

– Adriaan Koster
Nov 21 '18 at 9:50





Which title would you display if stories with the same id have different titles?

– Adriaan Koster
Nov 21 '18 at 9:50













@AdriaanKoster title is unique for an ID

– Hearaman
Nov 21 '18 at 9:52





@AdriaanKoster title is unique for an ID

– Hearaman
Nov 21 '18 at 9:52












3 Answers
3






active

oldest

votes


















4














A multimap can only store multiple values per key but what you want is to combine those multiple values so that you get one element that has the same id and title as well as a collection of keywords and targeting information. Thus it would probably be best to either have something like MultiStory or already have Story contain those collections.



I'd suggest using proper objects instead of just maps but with maps and Java 8 lambdas you could use compute() etc. to build maps that contain collections and combine maps that don't.



Here's an example of how you'd do it with maps. Note that this is very bad style and an example using proper pojos will follow:



Disclaimer: example based on the OP's code, not recommended (read text above)



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


Using POJOs



Here's a greatly simplified example of how you'd do it with proper Java objects (POJOs). Note that those are meant to resemble your code as much as possible and there are a lot of other issues but addressing those would be way too much here and better designed code would be a lot larger and probably harder to understand - after all it's just meant to show you a difference.



First let's define our classes (for simplicity I made the fields public, you'd normally not do that):



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 ;
}
}


Then let's reiterate the code above:



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


As you can see, there are no casts needed and it's clear what fields are available (though not necessarily filled) which makes it easier to reason about the code and spot errors (the compiler can help a lot here which it couldn't to in the example that uses maps).






share|improve this answer


























  • thanks for your help

    – Hearaman
    Nov 21 '18 at 9:28






  • 1





    +1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

    – Adriaan Koster
    Nov 21 '18 at 9:31



















2














Here is a solution using classes to represent the story and tags:



public static void main(String args) {
TagsCollector app = new TagsCollector();
app.go();
}

private void go() {
List<Story> stories = createStories();
System.out.println(stories);
Map<Long, Tags> tagsById = collectTags(stories);
tagsById.forEach((aLong, tags) -> System.out.println(tags));
}

private List<Story> createStories() {
return Arrays.asList(
new Story(1, "Onboarding", "new joinee", "finance"),
new Story(1, "Onboarding", "training", "HR")
);
}

private Map<Long, Tags> collectTags(List<Story> stories) {
Map<Long, Tags> tagsById = new HashMap<>();
stories.forEach(s -> {
Tags tags = tagsById.computeIfAbsent(s.id, v -> new Tags(s));
tags.getKeywords().add(s.getKeyword());
tags.getTargetings().add(s.getTargeting());
});
return tagsById;
}


Class used to represent the Story:



public class Story {

private final long id;
private final String title;
private final String keyword;
private final String targeting;

public Story(long id, String title, String keyword, String targeting) {
this.id = id;
this.title = title;
this.keyword = keyword;
this.targeting = targeting;
}

public long getId() {
return id;
}

public String getTitle() {
return title;
}

public String getKeyword() {
return keyword;
}

public String getTargeting() {
return targeting;
}

@Override
public String toString() {
return String.format("Story %s, title=%s, keyword=%s, targeting=%s", id, title, keyword, targeting);
}
}


Class used to represent the Tags:



public class Tags {
private final long id;
private final String title;
private final List<String> keywords = new ArrayList<>();
private final List<String> targetings = new ArrayList<>();

Tags(Story story) {
this.id = story.id;
this.title = story.title;
}

public List<String> getKeywords() {
return keywords;
}

public List<String> getTargetings() {
return targetings;
}

@Override
public String toString() {
return String.format("Tags for id %s, title:%s: keywords=%s, targetings=%s", id, title, keywords, targetings);
}
}


Output



[Story 1, title=Onboarding, keyword=new joinee, targeting=finance, Story 1, title=Onboarding, keyword=training, targeting=HR]
Tags for id 1, title:Onboarding: keywords=[new joinee, training], targetings=[finance, HR]





share|improve this answer


























  • Its really awesome. Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:39



















1














Yes, you can do that with a Multimap. First I would define a pojo for Story in order to make things clearer:



public class Story {
private int id;
private String title;
private String keyword;
private String targeting;
//getters setters
}


Second you need to define a key with hashcode and equals.



public static class StoryKey {
private final int id;
private final String title;

public StoryKey(int id, String title) {
this.id = id;
this.title = title;
}
//getters

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StoryKey storyKey = (StoryKey) o;

if (id != storyKey.id) return false;
return title != null ? title.equals(storyKey.title) : storyKey.title == null;
}

@Override
public int hashCode() {
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}


The code will look like:



  ArrayListMultimap<StoryKey, Story> multiMap = ArrayListMultimap.create();

List<Story> stories = new ArrayList();
Story story1 = new Story();

story1.setId(1);
story1.setTitle("Onboarding");
story1.setKeyword("training");
story1.setTargeting("HR");

Story story2 = new Story();

story2.setId(1);
story2.setTitle("Onboarding");
story2.setKeyword("new joinee,");
story2.setTargeting("finance");

stories.add(story1);
stories.add(story2);

System.out.println(stories);


stories.
forEach((story) -> {
multiMap.put(new StoryKey(story.getId(), story.getTitle()), story);
});

multiMap.keys().forEach(key ->
System.out.println(
"id =" + key.getId() +
" title =" + key.getTitle()+
"keyword =" + multiMap.get(key).stream().map(story->story.getKeyword()).collect(Collectors.toList()).toString()+
"targeting ="+ multiMap.get(key).stream().map(story->story.getTargeting()).collect(Collectors.toList()).toString())
);





share|improve this answer
























  • Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:47











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408742%2fhow-to-collect-properties-of-listmap-by-unique-property-using-multimap%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














A multimap can only store multiple values per key but what you want is to combine those multiple values so that you get one element that has the same id and title as well as a collection of keywords and targeting information. Thus it would probably be best to either have something like MultiStory or already have Story contain those collections.



I'd suggest using proper objects instead of just maps but with maps and Java 8 lambdas you could use compute() etc. to build maps that contain collections and combine maps that don't.



Here's an example of how you'd do it with maps. Note that this is very bad style and an example using proper pojos will follow:



Disclaimer: example based on the OP's code, not recommended (read text above)



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


Using POJOs



Here's a greatly simplified example of how you'd do it with proper Java objects (POJOs). Note that those are meant to resemble your code as much as possible and there are a lot of other issues but addressing those would be way too much here and better designed code would be a lot larger and probably harder to understand - after all it's just meant to show you a difference.



First let's define our classes (for simplicity I made the fields public, you'd normally not do that):



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 ;
}
}


Then let's reiterate the code above:



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


As you can see, there are no casts needed and it's clear what fields are available (though not necessarily filled) which makes it easier to reason about the code and spot errors (the compiler can help a lot here which it couldn't to in the example that uses maps).






share|improve this answer


























  • thanks for your help

    – Hearaman
    Nov 21 '18 at 9:28






  • 1





    +1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

    – Adriaan Koster
    Nov 21 '18 at 9:31
















4














A multimap can only store multiple values per key but what you want is to combine those multiple values so that you get one element that has the same id and title as well as a collection of keywords and targeting information. Thus it would probably be best to either have something like MultiStory or already have Story contain those collections.



I'd suggest using proper objects instead of just maps but with maps and Java 8 lambdas you could use compute() etc. to build maps that contain collections and combine maps that don't.



Here's an example of how you'd do it with maps. Note that this is very bad style and an example using proper pojos will follow:



Disclaimer: example based on the OP's code, not recommended (read text above)



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


Using POJOs



Here's a greatly simplified example of how you'd do it with proper Java objects (POJOs). Note that those are meant to resemble your code as much as possible and there are a lot of other issues but addressing those would be way too much here and better designed code would be a lot larger and probably harder to understand - after all it's just meant to show you a difference.



First let's define our classes (for simplicity I made the fields public, you'd normally not do that):



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 ;
}
}


Then let's reiterate the code above:



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


As you can see, there are no casts needed and it's clear what fields are available (though not necessarily filled) which makes it easier to reason about the code and spot errors (the compiler can help a lot here which it couldn't to in the example that uses maps).






share|improve this answer


























  • thanks for your help

    – Hearaman
    Nov 21 '18 at 9:28






  • 1





    +1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

    – Adriaan Koster
    Nov 21 '18 at 9:31














4












4








4







A multimap can only store multiple values per key but what you want is to combine those multiple values so that you get one element that has the same id and title as well as a collection of keywords and targeting information. Thus it would probably be best to either have something like MultiStory or already have Story contain those collections.



I'd suggest using proper objects instead of just maps but with maps and Java 8 lambdas you could use compute() etc. to build maps that contain collections and combine maps that don't.



Here's an example of how you'd do it with maps. Note that this is very bad style and an example using proper pojos will follow:



Disclaimer: example based on the OP's code, not recommended (read text above)



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


Using POJOs



Here's a greatly simplified example of how you'd do it with proper Java objects (POJOs). Note that those are meant to resemble your code as much as possible and there are a lot of other issues but addressing those would be way too much here and better designed code would be a lot larger and probably harder to understand - after all it's just meant to show you a difference.



First let's define our classes (for simplicity I made the fields public, you'd normally not do that):



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 ;
}
}


Then let's reiterate the code above:



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


As you can see, there are no casts needed and it's clear what fields are available (though not necessarily filled) which makes it easier to reason about the code and spot errors (the compiler can help a lot here which it couldn't to in the example that uses maps).






share|improve this answer















A multimap can only store multiple values per key but what you want is to combine those multiple values so that you get one element that has the same id and title as well as a collection of keywords and targeting information. Thus it would probably be best to either have something like MultiStory or already have Story contain those collections.



I'd suggest using proper objects instead of just maps but with maps and Java 8 lambdas you could use compute() etc. to build maps that contain collections and combine maps that don't.



Here's an example of how you'd do it with maps. Note that this is very bad style and an example using proper pojos will follow:



Disclaimer: example based on the OP's code, not recommended (read text above)



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


Using POJOs



Here's a greatly simplified example of how you'd do it with proper Java objects (POJOs). Note that those are meant to resemble your code as much as possible and there are a lot of other issues but addressing those would be way too much here and better designed code would be a lot larger and probably harder to understand - after all it's just meant to show you a difference.



First let's define our classes (for simplicity I made the fields public, you'd normally not do that):



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 ;
}
}


Then let's reiterate the code above:



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


As you can see, there are no casts needed and it's clear what fields are available (though not necessarily filled) which makes it easier to reason about the code and spot errors (the compiler can help a lot here which it couldn't to in the example that uses maps).







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 9:51

























answered Nov 21 '18 at 9:26









ThomasThomas

70k1091128




70k1091128













  • thanks for your help

    – Hearaman
    Nov 21 '18 at 9:28






  • 1





    +1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

    – Adriaan Koster
    Nov 21 '18 at 9:31



















  • thanks for your help

    – Hearaman
    Nov 21 '18 at 9:28






  • 1





    +1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

    – Adriaan Koster
    Nov 21 '18 at 9:31

















thanks for your help

– Hearaman
Nov 21 '18 at 9:28





thanks for your help

– Hearaman
Nov 21 '18 at 9:28




1




1





+1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

– Adriaan Koster
Nov 21 '18 at 9:31





+1 on using proper classes. It's a code smell to use maps to group related fields. It doesn't make the intent clear and defeats type safety.

– Adriaan Koster
Nov 21 '18 at 9:31













2














Here is a solution using classes to represent the story and tags:



public static void main(String args) {
TagsCollector app = new TagsCollector();
app.go();
}

private void go() {
List<Story> stories = createStories();
System.out.println(stories);
Map<Long, Tags> tagsById = collectTags(stories);
tagsById.forEach((aLong, tags) -> System.out.println(tags));
}

private List<Story> createStories() {
return Arrays.asList(
new Story(1, "Onboarding", "new joinee", "finance"),
new Story(1, "Onboarding", "training", "HR")
);
}

private Map<Long, Tags> collectTags(List<Story> stories) {
Map<Long, Tags> tagsById = new HashMap<>();
stories.forEach(s -> {
Tags tags = tagsById.computeIfAbsent(s.id, v -> new Tags(s));
tags.getKeywords().add(s.getKeyword());
tags.getTargetings().add(s.getTargeting());
});
return tagsById;
}


Class used to represent the Story:



public class Story {

private final long id;
private final String title;
private final String keyword;
private final String targeting;

public Story(long id, String title, String keyword, String targeting) {
this.id = id;
this.title = title;
this.keyword = keyword;
this.targeting = targeting;
}

public long getId() {
return id;
}

public String getTitle() {
return title;
}

public String getKeyword() {
return keyword;
}

public String getTargeting() {
return targeting;
}

@Override
public String toString() {
return String.format("Story %s, title=%s, keyword=%s, targeting=%s", id, title, keyword, targeting);
}
}


Class used to represent the Tags:



public class Tags {
private final long id;
private final String title;
private final List<String> keywords = new ArrayList<>();
private final List<String> targetings = new ArrayList<>();

Tags(Story story) {
this.id = story.id;
this.title = story.title;
}

public List<String> getKeywords() {
return keywords;
}

public List<String> getTargetings() {
return targetings;
}

@Override
public String toString() {
return String.format("Tags for id %s, title:%s: keywords=%s, targetings=%s", id, title, keywords, targetings);
}
}


Output



[Story 1, title=Onboarding, keyword=new joinee, targeting=finance, Story 1, title=Onboarding, keyword=training, targeting=HR]
Tags for id 1, title:Onboarding: keywords=[new joinee, training], targetings=[finance, HR]





share|improve this answer


























  • Its really awesome. Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:39
















2














Here is a solution using classes to represent the story and tags:



public static void main(String args) {
TagsCollector app = new TagsCollector();
app.go();
}

private void go() {
List<Story> stories = createStories();
System.out.println(stories);
Map<Long, Tags> tagsById = collectTags(stories);
tagsById.forEach((aLong, tags) -> System.out.println(tags));
}

private List<Story> createStories() {
return Arrays.asList(
new Story(1, "Onboarding", "new joinee", "finance"),
new Story(1, "Onboarding", "training", "HR")
);
}

private Map<Long, Tags> collectTags(List<Story> stories) {
Map<Long, Tags> tagsById = new HashMap<>();
stories.forEach(s -> {
Tags tags = tagsById.computeIfAbsent(s.id, v -> new Tags(s));
tags.getKeywords().add(s.getKeyword());
tags.getTargetings().add(s.getTargeting());
});
return tagsById;
}


Class used to represent the Story:



public class Story {

private final long id;
private final String title;
private final String keyword;
private final String targeting;

public Story(long id, String title, String keyword, String targeting) {
this.id = id;
this.title = title;
this.keyword = keyword;
this.targeting = targeting;
}

public long getId() {
return id;
}

public String getTitle() {
return title;
}

public String getKeyword() {
return keyword;
}

public String getTargeting() {
return targeting;
}

@Override
public String toString() {
return String.format("Story %s, title=%s, keyword=%s, targeting=%s", id, title, keyword, targeting);
}
}


Class used to represent the Tags:



public class Tags {
private final long id;
private final String title;
private final List<String> keywords = new ArrayList<>();
private final List<String> targetings = new ArrayList<>();

Tags(Story story) {
this.id = story.id;
this.title = story.title;
}

public List<String> getKeywords() {
return keywords;
}

public List<String> getTargetings() {
return targetings;
}

@Override
public String toString() {
return String.format("Tags for id %s, title:%s: keywords=%s, targetings=%s", id, title, keywords, targetings);
}
}


Output



[Story 1, title=Onboarding, keyword=new joinee, targeting=finance, Story 1, title=Onboarding, keyword=training, targeting=HR]
Tags for id 1, title:Onboarding: keywords=[new joinee, training], targetings=[finance, HR]





share|improve this answer


























  • Its really awesome. Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:39














2












2








2







Here is a solution using classes to represent the story and tags:



public static void main(String args) {
TagsCollector app = new TagsCollector();
app.go();
}

private void go() {
List<Story> stories = createStories();
System.out.println(stories);
Map<Long, Tags> tagsById = collectTags(stories);
tagsById.forEach((aLong, tags) -> System.out.println(tags));
}

private List<Story> createStories() {
return Arrays.asList(
new Story(1, "Onboarding", "new joinee", "finance"),
new Story(1, "Onboarding", "training", "HR")
);
}

private Map<Long, Tags> collectTags(List<Story> stories) {
Map<Long, Tags> tagsById = new HashMap<>();
stories.forEach(s -> {
Tags tags = tagsById.computeIfAbsent(s.id, v -> new Tags(s));
tags.getKeywords().add(s.getKeyword());
tags.getTargetings().add(s.getTargeting());
});
return tagsById;
}


Class used to represent the Story:



public class Story {

private final long id;
private final String title;
private final String keyword;
private final String targeting;

public Story(long id, String title, String keyword, String targeting) {
this.id = id;
this.title = title;
this.keyword = keyword;
this.targeting = targeting;
}

public long getId() {
return id;
}

public String getTitle() {
return title;
}

public String getKeyword() {
return keyword;
}

public String getTargeting() {
return targeting;
}

@Override
public String toString() {
return String.format("Story %s, title=%s, keyword=%s, targeting=%s", id, title, keyword, targeting);
}
}


Class used to represent the Tags:



public class Tags {
private final long id;
private final String title;
private final List<String> keywords = new ArrayList<>();
private final List<String> targetings = new ArrayList<>();

Tags(Story story) {
this.id = story.id;
this.title = story.title;
}

public List<String> getKeywords() {
return keywords;
}

public List<String> getTargetings() {
return targetings;
}

@Override
public String toString() {
return String.format("Tags for id %s, title:%s: keywords=%s, targetings=%s", id, title, keywords, targetings);
}
}


Output



[Story 1, title=Onboarding, keyword=new joinee, targeting=finance, Story 1, title=Onboarding, keyword=training, targeting=HR]
Tags for id 1, title:Onboarding: keywords=[new joinee, training], targetings=[finance, HR]





share|improve this answer















Here is a solution using classes to represent the story and tags:



public static void main(String args) {
TagsCollector app = new TagsCollector();
app.go();
}

private void go() {
List<Story> stories = createStories();
System.out.println(stories);
Map<Long, Tags> tagsById = collectTags(stories);
tagsById.forEach((aLong, tags) -> System.out.println(tags));
}

private List<Story> createStories() {
return Arrays.asList(
new Story(1, "Onboarding", "new joinee", "finance"),
new Story(1, "Onboarding", "training", "HR")
);
}

private Map<Long, Tags> collectTags(List<Story> stories) {
Map<Long, Tags> tagsById = new HashMap<>();
stories.forEach(s -> {
Tags tags = tagsById.computeIfAbsent(s.id, v -> new Tags(s));
tags.getKeywords().add(s.getKeyword());
tags.getTargetings().add(s.getTargeting());
});
return tagsById;
}


Class used to represent the Story:



public class Story {

private final long id;
private final String title;
private final String keyword;
private final String targeting;

public Story(long id, String title, String keyword, String targeting) {
this.id = id;
this.title = title;
this.keyword = keyword;
this.targeting = targeting;
}

public long getId() {
return id;
}

public String getTitle() {
return title;
}

public String getKeyword() {
return keyword;
}

public String getTargeting() {
return targeting;
}

@Override
public String toString() {
return String.format("Story %s, title=%s, keyword=%s, targeting=%s", id, title, keyword, targeting);
}
}


Class used to represent the Tags:



public class Tags {
private final long id;
private final String title;
private final List<String> keywords = new ArrayList<>();
private final List<String> targetings = new ArrayList<>();

Tags(Story story) {
this.id = story.id;
this.title = story.title;
}

public List<String> getKeywords() {
return keywords;
}

public List<String> getTargetings() {
return targetings;
}

@Override
public String toString() {
return String.format("Tags for id %s, title:%s: keywords=%s, targetings=%s", id, title, keywords, targetings);
}
}


Output



[Story 1, title=Onboarding, keyword=new joinee, targeting=finance, Story 1, title=Onboarding, keyword=training, targeting=HR]
Tags for id 1, title:Onboarding: keywords=[new joinee, training], targetings=[finance, HR]






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 10:39

























answered Nov 21 '18 at 10:28









Adriaan KosterAdriaan Koster

12.8k33248




12.8k33248













  • Its really awesome. Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:39



















  • Its really awesome. Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:39

















Its really awesome. Thanks for your support

– Hearaman
Nov 21 '18 at 10:39





Its really awesome. Thanks for your support

– Hearaman
Nov 21 '18 at 10:39











1














Yes, you can do that with a Multimap. First I would define a pojo for Story in order to make things clearer:



public class Story {
private int id;
private String title;
private String keyword;
private String targeting;
//getters setters
}


Second you need to define a key with hashcode and equals.



public static class StoryKey {
private final int id;
private final String title;

public StoryKey(int id, String title) {
this.id = id;
this.title = title;
}
//getters

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StoryKey storyKey = (StoryKey) o;

if (id != storyKey.id) return false;
return title != null ? title.equals(storyKey.title) : storyKey.title == null;
}

@Override
public int hashCode() {
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}


The code will look like:



  ArrayListMultimap<StoryKey, Story> multiMap = ArrayListMultimap.create();

List<Story> stories = new ArrayList();
Story story1 = new Story();

story1.setId(1);
story1.setTitle("Onboarding");
story1.setKeyword("training");
story1.setTargeting("HR");

Story story2 = new Story();

story2.setId(1);
story2.setTitle("Onboarding");
story2.setKeyword("new joinee,");
story2.setTargeting("finance");

stories.add(story1);
stories.add(story2);

System.out.println(stories);


stories.
forEach((story) -> {
multiMap.put(new StoryKey(story.getId(), story.getTitle()), story);
});

multiMap.keys().forEach(key ->
System.out.println(
"id =" + key.getId() +
" title =" + key.getTitle()+
"keyword =" + multiMap.get(key).stream().map(story->story.getKeyword()).collect(Collectors.toList()).toString()+
"targeting ="+ multiMap.get(key).stream().map(story->story.getTargeting()).collect(Collectors.toList()).toString())
);





share|improve this answer
























  • Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:47
















1














Yes, you can do that with a Multimap. First I would define a pojo for Story in order to make things clearer:



public class Story {
private int id;
private String title;
private String keyword;
private String targeting;
//getters setters
}


Second you need to define a key with hashcode and equals.



public static class StoryKey {
private final int id;
private final String title;

public StoryKey(int id, String title) {
this.id = id;
this.title = title;
}
//getters

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StoryKey storyKey = (StoryKey) o;

if (id != storyKey.id) return false;
return title != null ? title.equals(storyKey.title) : storyKey.title == null;
}

@Override
public int hashCode() {
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}


The code will look like:



  ArrayListMultimap<StoryKey, Story> multiMap = ArrayListMultimap.create();

List<Story> stories = new ArrayList();
Story story1 = new Story();

story1.setId(1);
story1.setTitle("Onboarding");
story1.setKeyword("training");
story1.setTargeting("HR");

Story story2 = new Story();

story2.setId(1);
story2.setTitle("Onboarding");
story2.setKeyword("new joinee,");
story2.setTargeting("finance");

stories.add(story1);
stories.add(story2);

System.out.println(stories);


stories.
forEach((story) -> {
multiMap.put(new StoryKey(story.getId(), story.getTitle()), story);
});

multiMap.keys().forEach(key ->
System.out.println(
"id =" + key.getId() +
" title =" + key.getTitle()+
"keyword =" + multiMap.get(key).stream().map(story->story.getKeyword()).collect(Collectors.toList()).toString()+
"targeting ="+ multiMap.get(key).stream().map(story->story.getTargeting()).collect(Collectors.toList()).toString())
);





share|improve this answer
























  • Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:47














1












1








1







Yes, you can do that with a Multimap. First I would define a pojo for Story in order to make things clearer:



public class Story {
private int id;
private String title;
private String keyword;
private String targeting;
//getters setters
}


Second you need to define a key with hashcode and equals.



public static class StoryKey {
private final int id;
private final String title;

public StoryKey(int id, String title) {
this.id = id;
this.title = title;
}
//getters

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StoryKey storyKey = (StoryKey) o;

if (id != storyKey.id) return false;
return title != null ? title.equals(storyKey.title) : storyKey.title == null;
}

@Override
public int hashCode() {
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}


The code will look like:



  ArrayListMultimap<StoryKey, Story> multiMap = ArrayListMultimap.create();

List<Story> stories = new ArrayList();
Story story1 = new Story();

story1.setId(1);
story1.setTitle("Onboarding");
story1.setKeyword("training");
story1.setTargeting("HR");

Story story2 = new Story();

story2.setId(1);
story2.setTitle("Onboarding");
story2.setKeyword("new joinee,");
story2.setTargeting("finance");

stories.add(story1);
stories.add(story2);

System.out.println(stories);


stories.
forEach((story) -> {
multiMap.put(new StoryKey(story.getId(), story.getTitle()), story);
});

multiMap.keys().forEach(key ->
System.out.println(
"id =" + key.getId() +
" title =" + key.getTitle()+
"keyword =" + multiMap.get(key).stream().map(story->story.getKeyword()).collect(Collectors.toList()).toString()+
"targeting ="+ multiMap.get(key).stream().map(story->story.getTargeting()).collect(Collectors.toList()).toString())
);





share|improve this answer













Yes, you can do that with a Multimap. First I would define a pojo for Story in order to make things clearer:



public class Story {
private int id;
private String title;
private String keyword;
private String targeting;
//getters setters
}


Second you need to define a key with hashcode and equals.



public static class StoryKey {
private final int id;
private final String title;

public StoryKey(int id, String title) {
this.id = id;
this.title = title;
}
//getters

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StoryKey storyKey = (StoryKey) o;

if (id != storyKey.id) return false;
return title != null ? title.equals(storyKey.title) : storyKey.title == null;
}

@Override
public int hashCode() {
int result = id;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}


The code will look like:



  ArrayListMultimap<StoryKey, Story> multiMap = ArrayListMultimap.create();

List<Story> stories = new ArrayList();
Story story1 = new Story();

story1.setId(1);
story1.setTitle("Onboarding");
story1.setKeyword("training");
story1.setTargeting("HR");

Story story2 = new Story();

story2.setId(1);
story2.setTitle("Onboarding");
story2.setKeyword("new joinee,");
story2.setTargeting("finance");

stories.add(story1);
stories.add(story2);

System.out.println(stories);


stories.
forEach((story) -> {
multiMap.put(new StoryKey(story.getId(), story.getTitle()), story);
});

multiMap.keys().forEach(key ->
System.out.println(
"id =" + key.getId() +
" title =" + key.getTitle()+
"keyword =" + multiMap.get(key).stream().map(story->story.getKeyword()).collect(Collectors.toList()).toString()+
"targeting ="+ multiMap.get(key).stream().map(story->story.getTargeting()).collect(Collectors.toList()).toString())
);






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 '18 at 9:51









user1121883user1121883

3,95232427




3,95232427













  • Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:47



















  • Thanks for your support

    – Hearaman
    Nov 21 '18 at 10:47

















Thanks for your support

– Hearaman
Nov 21 '18 at 10:47





Thanks for your support

– Hearaman
Nov 21 '18 at 10:47


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408742%2fhow-to-collect-properties-of-listmap-by-unique-property-using-multimap%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to change which sound is reproduced for terminal bell?

Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

Can I use Tabulator js library in my java Spring + Thymeleaf project?