0

How do achieve this with one line ?

I am currently trying to do this

Example :

{{"id" :"2", values: ["10","11", "12"]} , {"id" : "3", values : ["23"]}}

to

{{"id" :"2","value": "10"},{"id": "2","value":"11"},
 {"id" :"3","value":"23"} , {"id" : "2", "value":"12"}}

My java code is

Map<Integer, List<Integer>> attrMap = new HashMap<>();
//getAllData() & item.getValues() both returns List

getAllData().forEach(item - > {
    item.getValues().forEach(val - > {
        attrMap.computeIfAbsent(item.getId(), (k) - > 
        new ArrayList < > ()).add(val.getValue());
    });
});

How can i do it only 1 line ?

4
  • 3
    By removing the line-breaks ... ? Commented Jul 14, 2017 at 8:52
  • This question is kinda absurd. First of all the most important is REAL optimisation (time + data), the number of lines isjust for readability. When I see that some piece of code won'tchange anymore sometimes I remove line-breaks so i can scroll the code faster. But thats all. Commented Jul 14, 2017 at 8:56
  • I mean to say to avoid two foreach loop & do it with one foreach loop. Is it possible? Commented Jul 14, 2017 at 9:19
  • Yes, ids are unique Commented Jul 14, 2017 at 9:52

2 Answers 2

5

Since the IDs are unique, you can do it like

Map<Integer, List<Integer>> attrMap = getAllData().stream()
  .collect(Collectors.toMap(
    item -> item.getId(),
    item -> item.getValues().stream().map(i->i.getValue()).collect(Collectors.toList())));

But, of course, this will still have the performance characteristics of two nested loops. It would support parallel processing, though, but I doubt that your data will be large enough to draw a benefit from parallel processing.

Further, note that the resulting map still structurally matches your first pattern,

{{"id" :"2", values: ["10","11", "12"]} , {"id" : "3", values : ["23"]}}

you just converted item to an entry of the result Map and val to an element of a List<Integer>.

Sign up to request clarification or add additional context in comments.

Comments

2

Assuming you have your input like this:

static class Data {
    private final int id;

    private final List<Integer> values;

    public int getId() {
        return id;
    }

    public List<Integer> getValues() {
        return values;
    }

    public Data(int id, List<Integer> values) {
        super();
        this.id = id;
        this.values = values;
    }
}

It could be done via:

 List<SimpleEntry<Integer, Integer>> result = Arrays.asList(
           new Data(2, Arrays.asList(10, 11, 12)), 
           new Data(3, Arrays.asList(23)))
              .stream()
              .flatMap(d -> d.getValues().stream().map(x -> new AbstractMap.SimpleEntry<>(d.getId(), x)))
            .collect(Collectors.toList());

    System.out.println(result); // [2=10, 2=11, 2=12, 3=23]

I am collecting those to Pair or AbstractMap.SimpleEntry.

2 Comments

Don't think this is much shorter than the code from the OP.
I mean to say to avoid two foreach loop & do it with one foreach loop. Is it possible?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.