3

I'm having trouble figuring out how to deal with cleaning up some of my code to do this:

I have a List of a Context objects. Each Context has a String userId and a Map<String, SomeObject> someObjects.

I want to flatten this into a Map<String, SomeObjects> where the kep is the userId. To be more concrete:

class Context {
    String userId;
    Map<String, List<SomeObject>> // the String here is something other than userId
    // other stuff, getters/setters
}

Given List<Context>, I want to get Map<String, List<SomeObject> but where the String is actually the userId.

Is there a clean way to do this?

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
CustardBun
  • 3,457
  • 8
  • 39
  • 65
  • What's the name of the `Map>` variable? Does each context have a unique `userId`? Each `userId` has many `List`s in its adjacent map -- is your intent to concatenate all of those lists together? – John Kugelman Apr 03 '17 at 22:40
  • [Duplicate Question](http://stackoverflow.com/questions/20363719/java-8-listv-into-mapk-v) – hkasera Apr 03 '17 at 22:40
  • there is more the one clean way, but it is not clear where the userId is stored and how can we get it (and the list of objects) the from the context – freedev Apr 03 '17 at 22:46
  • The userId is part of the Context - I'll edit the original question. Both are parts of the Context (the userId and the Map) – CustardBun Apr 03 '17 at 22:51
  • 1
    Do you just want all the values of the `Map>` to be in one `List` for each user? If so, do you want to keep duplicates? If not, would a `Set` work? – Bohemian Apr 03 '17 at 22:53
  • @Bohemian - A set should be fine as well. I don't think I would want duplicates in here. The values for Map> should be combined into one List mapped by the userId instead of the String "category". – CustardBun Apr 03 '17 at 22:55
  • @Mei, kindly have a look at my code too and let me know if it helps. I would highly appreciate your upvote :) Thank you – Devendra Lattu Apr 03 '17 at 23:46

2 Answers2

3

Assuming a Context has a String userid and a List<SomeObject> someObjects:

Map<String, Set<SomeObject>> map = contexts.stream()
    .collect(Collectors.toMap(Context::getUserid, 
       c -> c.getSomeObjects().values().stream()
      .flatMap(Collection::stream)
      .collect(Collectors.toSet())
     ));

The key points here are the use of toMap() to collect by userid and flatmap() to turn a Stream<List<SomeObject>> into a Stream<SomeObject> so you can collect them into one collection.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Creating class Context to hold String and Map datatypes

class Context {
    String userId;
    Map<String, List<Integer>> map;

    public Context(String s, List<Integer> list) {
        userId = s;
        map = new HashMap<>();
        map.put(userId, list);
    }

    public void setValues(String s, List<Integer> list) {
        map.put(s, list);
    }

}

Now creating the Solution class which has List<Context>

public class Solution {

    public static void main(String[] args) {

        List<Integer> list;

        // Context c1
        list = new ArrayList<>(Arrays.asList(1, 2, 3));
        Context c1 = new Context("dev", list);

        list = new ArrayList<>(Arrays.asList(-1, -3));
        c1.setValues("dev2", list);

        list = new ArrayList<>(Arrays.asList(-6, -3));
        c1.setValues("dev3", list);

        // Context c2
        list = new ArrayList<>(Arrays.asList(12, 15, 18));
        Context c2 = new Context("macy", list);

        list = new ArrayList<>(Arrays.asList(-12, -13));
        c2.setValues("macy2", list);

        list = new ArrayList<>(Arrays.asList(-8, -18));
        c2.setValues("macy3", list);

        // Context c3
        list = new ArrayList<>(Arrays.asList(20, 30));
        Context c3 = new Context("bob", list);

        list = new ArrayList<>(Arrays.asList(-31, -32));
        c3.setValues("bob2", list);

        // Context List
        List<Context> contextList = new ArrayList<>();
        contextList.addAll(Arrays.asList(c1, c2, c3));

        retrieveRecords(contextList);
    }

    private static void retrieveRecords(List<Context> contextList) {
        // regular way of retrieving map values
        for (Context c : contextList) {
            System.out.println(c.map);
        }

        System.out.println();

        // Retrieving only those records which has String key as userID
        for (Context c : contextList) {
            System.out.println(c.userId + "\t=>\t" + c.map.get(c.userId));
        }
    }

}

enter image description here

Devendra Lattu
  • 2,732
  • 2
  • 18
  • 27
  • Thanks for your answer, but my main problem was "I want to flatten this into a Map where the key is the userId" so selectively printing out records would not solve my specific issue. Regardless, you will get my upvote for your different perspective! – CustardBun Apr 03 '17 at 23:53
  • I appreciate it! – Devendra Lattu Apr 03 '17 at 23:54