write a generic method to print out the element of listoflist using stream in java

Viewed 29

I am new to Java Generics. I have two List with different type Object and Integer and i want to write a generic method which takes the list of lists and want to print out the containing elements inside the list. Example

  List<Object> list1 = List.of(1, List.of(2, 3, 4, List.of(5)), List.of(6, 7));
    genericmethod(list1);
    System.out.println();
  
    List<Integer> list2 = List.of(1, 2, 3, 4, 5, 6, 7, 8);
    genericmethod(list2);
    System.out.println();
    both the method should print 1,2,3,4,5,6,7,8

    I tried with

     public static void genericmethod(List<?> list) { 
         list.stream().forEach(System.out::println);
     }

Output : 1 [2, 3, 4, [5]] [6, 7]

and

1 2 3 4 5 6 7 8

But i want to print out just 1,2,3,4,5,6,7,8 from both the list as a result.

1 Answers

In decades of Java development, I've never found a case where this sort of structure was the right approach. I'd suggest finding a type-safe way to store your data, perhaps using a simple custom type.

You can't do this in a type-safe way, as the common ancestor of List and Integer is Object. You have to test the type dynamically and act accordingly:

static Stream<Object> expand(Collection<?> elements) {
  return elements.stream()
    .flatMap(e -> e instanceof Collection col ? col.stream() : Stream.of(e));
}

Your example would use such a function like this:

expand(list1).forEach(System.out::print);
System.out.println();
expand(list2).forEach(System.out::print);
System.out.println();

If you know that all the "leaf" elements of your input are a specific type—say, Integer—you can perform type checking at runtime and write a generic method:

static <T> Stream<T> expand(Class<? extends T> t, Collection<?> elements) {
  return elements.stream()
    .flatMap(e -> e instanceof Collection col ? col.stream() : Stream.of(t.cast(e)));
}

int total = expand(Integer.class, list1).mapToInt(Integer::intValue).sum();

Perhaps the lists can be nested to any depth:

static <T> Stream<T> expand(Class<? extends T> t, Collection<?> elements) {
  return elements.stream()
    .flatMap(e -> e instanceof Collection col ? expand(t, col) : Stream.of(t.cast(e)));
}
Related