java.lang.UnsupportedOperationException当我没有使用ImmutableList时,ImmutableList.remove

时间:2016-03-27 17:00:24

标签: java list immutability java-stream

我有这段代码

    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;
            }
        }
    }

我得到了这个例外,甚至认为我不使用ImmutableList

我挖掘了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)

使用此代码将获得相同的交集逻辑,但效率较低。

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

你会如何重写交叉码?

为什么我还是会得到这个错误?

3 个答案:

答案 0 :(得分:2)

您可以将getConnectedDevices()方法中的设备ID列表传递给新的ArrayList:

 final List<String> connectedIds = new ArrayList<>(getConnectedDevices());

这会将ImmutableList中的所有值复制到ArrayList中,您可以从中删除项目。

您使用流提供的示例看起来更简洁易懂。除非确认的性能影响是不可接受的,否则它看起来就像是最好的方法。

答案 1 :(得分:1)

制作已连接设备ID List的副本。这个副本将是可变的。

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:id的集合应该是Set而不是列表。 E.g。

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

答案 2 :(得分:0)

来自java doc,它说。它并不能保证可变性。

public static <T> Collector<T,?,List<T>> toList()

返回将输入元素累积到新List中的Collector。返回的List的类型,可变性,可序列化或线程安全性无法保证;如果需要更多地控制返回的List,请使用toCollection(Supplier)。 类型参数: T - 输入元素的类型 返回: 收集器按顺序将所有输入元素收集到List中。

您可以尝试打印getConnectedDevices()返回的列表类型。