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

问题描述 投票:0回答:4

我有这个代码

    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());

你会如何重写交叉点代码?

为什么我还是会收到此错误?

java list immutability java-stream
4个回答
3
投票

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

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

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

您提供的使用流的示例看起来更加简洁和易于理解。除非它确实对性能产生了不可接受的影响,否则它看起来是最好的方法。


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
而不是列表。例如

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

0
投票

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

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

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

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


0
投票

当您由于某些方法(例如 List.of(object1, object2, ...) 或 Arrays.asList(...))而无意使用不可变列表时,可能会遇到“UnsupportedOperationException”。这些方法生成固定大小的列表,这可能会产生可变性的错觉。如果您无意中修改了使用这些方法创建的列表,则会导致“UnsupportedOperationException”,因为列表本身是不可变的。

© www.soinside.com 2019 - 2024. All rights reserved.