2

I am trying to learn streaming in java 8. Following is my code :

Main.java

public class Main {
    public static void main(String[] args) {

        Person person = new Person("FirstName", "LastName");
        List<Person> personList = new ArrayList<>();
        personList.add(person);

        Place place = new Place("name", "country");
        List<Place> placeList = new ArrayList<>();
        placeList.add(place);


        List<List<Object>> objects = new ArrayList<>();
        objects.add(Collections.singletonList(personList));
        objects.add(Collections.singletonList(placeList));

        List<Object> persons = objects.get(0);
        List<String> firstNames = persons.stream()
                .map(o -> ((Person)o).getFirstName())
                .collect(Collectors.toList());

        firstNames.forEach(System.out::println);
    }
}

Person.java

@Data
public class Person {
    String firstName;
    String lastName;

    public Person(String firstName, String lastName) {
        setFirstName(firstName);
        setLastName(lastName);
    }
}

Place.java

@Data
public class Place {
    String name;
    String country;

    public Place(String name, String country) {
        setName(name);
        setCountry(country);
    }
}

Exception :

Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to Person
    at Main.lambda$main$0(Main.java:28)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Collections$2.tryAdvance(Collections.java:4717)
    at java.util.Collections$2.forEachRemaining(Collections.java:4725)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at Main.main(Main.java:29)

I have List of List which is holding Object (I am using Object since I want to use a different type of object to be stored into the collection). I am storing the collection of Person and collection of Place into this List of List collection.

Inside the streaming, I am trying to get the only firstName of all the persons. However, when I use lamba expression which goes through each element and get the firstName does not work with casting.

Question:

  1. Am I doing anything wrong?
  2. Is there any other way(other than map in streaming) to get all the FirstName of the Person Object with stream API?

1 Answer 1

6

personList is a List of Person

Collections.singletonList(personList) is a List of List of Person

objects is a List of List of List of Person/Place.

    List<Object> persons = objects.get(0);   // persons is a List of List of Person
    List<String> firstNames = persons.stream()  
    //each element in the stream is a List of Person, so you cannot cast it to Person.
            .map(o -> ((Person)o).getFirstName())
            .collect(Collectors.toList());

You can either remove the singletonList function so that you reduce a level of list:

    List<List<?>> objects = new ArrayList<>();
    objects.add(personList);
    objects.add(placeList);

or go deeper one list when you do map:

    List<String> firstNames = persons.stream() 
            //Because persons is declared as List of Objects, so you need to cast each element into a List before calling get 
            .map(o -> ((Person)((List)o).get(0))).getFirstName())
            .collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

4 Comments

To remove singletonList, you have to change the declaration to List<List<?>> objects, as personList and placeList do not have the type List<Object>.
@Holger Not necessarily. Object is a root class for everything and any object can be declared as Object. like `Object o = new ArrayList()"
That doesn’t matter. You can’t assign a List<Person> to a variable of type List<Object> and hence, you can’t store a List<Person> into a List<List<Object>>.
@Holger I see what you mean. Yes you are right. Updated answer

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.