simyaci
simyaci

Reputation: 93

Converting wrapped stream in another Stream in Java

I need to convert a wrapped stream in another stream to map.

public Map<String, MyObject> convert(Stream<Stream<MyObject>> myobjects) {
    Map<String, MyObject> processedTransactionMap = new HashMap<String, MyObject>();
    // convert process..  key of map is any String variable  of MyObject
    return processedTransactionMap;
}

Thank you.

Upvotes: 0

Views: 355

Answers (2)

Most Noble Rabbit
Most Noble Rabbit

Reputation: 2776

You can use flatMap operator:

Stream<Stream<MyObject>> myobjects = Stream.of(
        Stream.of(new MyObject("A", 1), new MyObject("B", 1)),
        Stream.of(new MyObject("C", 2), new MyObject("D", 2))
);

Map<String, MyObject> processedTransactionMap = myobjects
        .flatMap(stream -> stream) // flattening the inner streams
        .collect(Collectors.toMap(MyObject::getStr, o -> o));

System.out.println(processedTransactionMap);

Output:

{A=MyObject(str=A, integer=1), B=MyObject(str=B, integer=1), C=MyObject(str=C, integer=2), D=MyObject(str=D, integer=2)}

Assumption: Each MyObject instance has unique str value.

Upvotes: 1

josejuan
josejuan

Reputation: 9566

Since multiple MyObject could have the same String key you should explain how you need aggregate data.

Anyway, there are two main ways to do it; a full example could be:

public static void main(String... args) throws IOException {

    // aggregate all with same key
    Map<String, List<MyObject>> agg1 = makeExample()
            .flatMap(x -> x)        // stream of stream to one single stream
            .collect(groupingBy(    // group by
                    x -> x.key,     //      key
                    toList()));     //      if collision, aggregate to a list

    // aggregate with collision
    Map<String, MyObject> agg2 = makeExample()
            .flatMap(x -> x)
            .collect(toMap(                     // aggregate to single MyOject
                    x -> x.key,                 // grouping by key
                    x -> x,                     // taking MyObject
                    (a, b) -> new MyObject(     // if collision form a new one
                            a.key,              //      with that key
                            a.data + b.data))); //      addind data

    // print results
    System.out.println("== as list ==");
    agg1.forEach((key, ys) -> {
        System.out.printf("  ** %s%n", key);
        ys.forEach(y -> System.out.printf("    %s%n", y));
    });

    System.out.println();

    System.out.println("== joining ==");
    agg2.forEach((key, y) -> {
        System.out.printf("  ** %s%n", key);
        System.out.printf("    %s%n", y);
    });
}

static Stream<Stream<MyObject>> makeExample() {
    return IntStream.range(1, 3)
            .mapToObj(n -> IntStream.range(1, n + 1)
                    .mapToObj(j -> new MyObject(Integer.toString(n), j)));
}

static class MyObject {
    public String key;
    public int data;

    public MyObject(String key, int data) {
        this.key = key;
        this.data = data;
    }

    public String toString() {
        return String.format("{key: %s, data: %d}", key, data);
    }
}

with output

== as list ==
  ** 1
    {key: 1, data: 1}
  ** 2
    {key: 2, data: 1}
    {key: 2, data: 2}

== joining ==
  ** 1
    {key: 1, data: 1}
  ** 2
    {key: 2, data: 3}

Upvotes: 1

Related Questions