10

I have a list of array of 2 objects:

List<Object[2]>

Where object[0] is an Integer and object[1] is a String.

How can I stream the list and apply different functions on each object? So that, the result will be an array having:

result[0] = multiplication of all object[0]
result[1] = concatenation of all object[1]
Noor
  • 167
  • 1
  • 7

3 Answers3

11

You can achieve this with reduce() :

public void testStacko() {
    List<Object[]> list = new ArrayList<>();
    list.add(new Object[] {1, "foo"});
    list.add(new Object[] {6, "|bar"});
    list.add(new Object[] {15, "|baz"});
    Object[] array = list.stream()
                         .reduce(
                                  (obj1, obj2) -> 
                                   new Object[] {(int) obj1[0] * (int) obj2[0], 
                                                 (String) obj1[1] + (String) obj2[1]
                                                }
                                )
                         .get();
    System.out.println(array[0]); // 90
    System.out.println(array[1]); // foo|bar|baz
}
Vincent Passau
  • 794
  • 9
  • 22
11

With JDK-12, you can use

Object[] array = list.stream()
    .collect(Collectors.teeing(
        Collectors.reducing(1, a -> (Integer)a[0], (a,b) -> a * b),
        Collectors.mapping(a -> (String)a[1], Collectors.joining()),
        (i,s) -> new Object[] { i, s}
    ));

but you really should rethink your data structures.

This answer shows a version of the teeing collector which works under Java 8.

Holger
  • 267,107
  • 35
  • 402
  • 715
  • 2
    @GhostCat I always thought of a T connector or the Unix command `tee`. Don’t know whether “teeing” as a word predates that. – Holger Jun 18 '19 at 15:35
8

You already got a good technical answer, so let's add a distinct non-answer.

This here: List<Object[2]> feels sooooo wrong.

Why don't you use something like: List<Pair<Integer, String>>?!

In other words: do not give up on type information lightly. Do not misuse Object[] as a typeless container to stuff in already typed things. Java is a statically compiled language. Meaning: don't resist the forces of generics and strict typing, instead flow with them.

And the answer code turns into:

.reduce(p1, p2 -> new Pair<>(p1.first * p2.first, p1.second + p2.second))

Seriously: it starts by using Object[] ... and it ends with you switching to ruby 'cause dynamic typing!

GhostCat
  • 133,361
  • 24
  • 165
  • 234
  • I agree, it's much better with a Pair. – Vincent Passau Jun 18 '19 at 14:18
  • Because my list has more than 2 objects. I gave 2 objects list as an example. Pair definitely is better in the case of 2 objects. – Noor Jun 18 '19 at 15:26
  • 3
    @Noor then, any class type defining distinct fields with names and types is better than an array of differently typed elements whose meaning has to be guessed from their position. – Holger Jun 18 '19 at 15:37
  • @Holger agree. Am working on a POC right now and will have a class that will hold all of these objects. I Just wanted to know how to perform different functions on stream objects. – Noor Jun 18 '19 at 15:44