13

I have two lists as follow

List<String> names = Arrays.asList("James","John","Fred");
List<Integer> ages = Arrays.asList(25,35,15);

What i want to do is to print those two lists like so

James:25
John:35
Fred:15

It is easy to do it using the classic way

for(int i=0;i<names.size();i++){
    System.out.println(names.get(i)+":"+ages.get(i));
}

Is there a way to do it using Stream API java 8?

What i am able to do is to print only one single list

names.stream().forEach(System.out::println);
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
MChaker
  • 2,610
  • 2
  • 22
  • 38

3 Answers3

15

The easiest way is to create an IntStream to generate the indices, and then map each index to the String you want to create.

IntStream.range(0, Math.min(names.size(), ages.size()))
         .mapToObj(i -> names.get(i)+":"+ages.get(i))
         .forEach(System.out::println);

Also you might be interested in this SO question Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip), because this is the kind of functionality you're asking for.

Community
  • 1
  • 1
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
7

My StreamEx library has some syntactic sugar for this case:

StreamEx.zip(names, ages, (name, age) -> name+":"+age).forEach(System.out::println)

Basically inside it's the same as in accepted answer. The only difference is that IllegalArgumentException will be thrown if size of lists differs.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
1

While Alexis C. answer is correct, one would argue it is the easiest way to achieve requested behavior in Java 8. I propose:

int[] i = {0};
names.forEach(name -> {
    System.out.println(name + ages.get(i[0]++));
});

Or even without index:

List<Integer> agesCopy = new ArrayList<Integer>(ages);
names.forEach(name -> {
    System.out.println(name + agesCopy.remove(0));
});
kukis
  • 4,489
  • 6
  • 27
  • 50