How to remove under 18 years old from list?

I try to remove all the person under 18 years old from my list, so i have a class Person and this is what i tried in my Main:

import java.util.*;

public class Main {

    public static void main(String[] args) {
       
        Person person1 = new Person("Victor", 28, "meerdonk");
        Person person2 = new Person("Alex", 17, "antwerpen");
        Person person3 = new Person("Vlad", 15, "mechelen");

        List<Person> listOfPersons = List.of(person1, person2, person3);
   
        List<Person> adults = getLessThen18(listOfPersons); **//line 22**
        System.out.println(adults);
}   
 public static List<Person> getLessThen18(List<Person> personList) {

       for (Iterator<Person> iterator = personList.listIterator(); iterator.hasNext();){
           if (iterator.next().getAge() < 18 ) {
                iterator.remove(); **//line 40**
           }
       }
        return personList;
    }
}

So I try to iterate trough the list of persons and then if the person is under 18 to remove it. As i run the code i get this output :

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
    at java.base/java.util.ImmutableCollections$ListItr.remove(ImmutableCollections.java:380)
    at victor.Main.getLessThen18Iteration(Main.java:40)
    at victor.Main.main(Main.java:22)

Can someone please let me know what I did wrong?


Solution 1:

Your code (List.of) creates an immutable list of persons:

    List<Person> listOfPersons = List.of(person1, person2, person3);

So calling remove/add will cause an Exception - as in your case.

Also your method name is misleading, since you are changing/mutating the passed list parameter and not return a new list (as suggested by the return value).

A possible way to do it would be:

 public static List<Person> getLessThen18(List<Person> personList) {
    return personList.stream()
                     .filter(person -> person.getAge() < 18)
                     .collect(Collectors.toList());   
 }

Solution 2:

The problem here is the List.of. It returns an immutable List, which cannot be modified: Elements cannot be added, removed, or replaced.

Thus, you get an Exception when you try to call functions such as iterator.remove();.

There are these solutions:

  • Create a mutable List by copying the elements of the immutable List to a mutable one using a copy constructor:

    List<Person> listOfPersons = new ArrayList(List.of(person1, person2, person3));

  • Filter the existing List and create a new one (leaving the original List ontouched):

    return personList.stream().filter(person->person.getAge()<18).collect(Collectors.toList());

- Create a mutable List right away using Arrays.asList (which returns an ArrayList) List listOfPersons = Arrays.asList(person1, person2, person3);`

EDIT: Arrays.asList creates an ArrayList, but it's a different class (private static inside of Arrays) than anyone would assume..