Search code examples
javalistimmutabilityjava-stream

java.lang.UnsupportedOperationException ImmutableList.remove when i didn't use ImmutableList


I have this code

    final List<String> connectedIds = getConnectedDevices();
    final List<Device> allDbDevicesAsList = getAllDbDevicesAsList();

    List<Device> connectedDevices = new ArrayList<>();
    for (int i = 0; i < allDbDevicesAsList.size(); i++) {
        int size = connectedIds.size();
        for (int j = 0; j < size; j++) {
            final Device currentDevice = allDbDevicesAsList.get(i);
            if(currentDevice.uuid == connectedIds.get(j))
            {
                connectedDevices.add(currentDevice);
                connectedIds.remove(j);
                break;
            }
        }
    }

and I get this exception, even thought I don't use ImmutableList

and I dug into all the methods calls of getConnectedDevices()

java.lang.UnsupportedOperationException
    at com.google.common.collect.ImmutableList.remove(ImmutableList.java:479)
    at com.waze.automation.client.services.web.lib.devices.DevicesServiceLocal.getDevices(DevicesServiceLocal.java:66)
    at com.waze.mobileautomation.devices.DevicesServiceLocalTest.testGetAvailableDevices_returnsOnly(DevicesServiceLocalTest.java:194)

using this code will gain same intersection logic, but is less efficient.

    List<Device> connectedDevices = allDbDevicesAsList.stream()
            .filter(item -> connectedIds.contains(item.uuid))
            .collect(Collectors.toList());

How would you re-write the intersection code?

why do i get this error anyways?


Solution

  • Make a copy of the connected device id List. This copy will be mutable.

    List<String> connectedIds = new ArrayList<String>(getConnectedDevices());
    List<Device> allDbDevicesAsList = getAllDbDevicesAsList();
    
    List<Device> connectedDevices = new ArrayList<Device>();
    
    for (int i = 0; i < allDbDevicesAsList.size(); i++) {
        Device currentDevice = allDbDevicesAsList.get(i);
        boolean removed = connectedIds.remove(currentDevice.uuid);
        if (removed) {
            connectedDevices.add(currentDevice);
        }
    }
    

    PS: The id's collection should be a Set instead of a list. E.g.

    Set<String> connectedIds = new HashSet<String>(getConnectedDevices());