2016-03-27 1 views
1

J'ai ce codejava.lang.UnsupportedOperationException ImmutableList.remove quand je n'ai pas utilisé ImmutableList

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

et je reçois cette exception, même pensé que je ne me ImmutableList

et je creusais dans toutes les méthodes appels 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) 

en utilisant ce code gagnera même logique d'intersection, mais il est moins efficace.

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

Comment réécrire le code d'intersection? Pourquoi ai-je cette erreur de toute façon?

+3

Il semble que 'getConnectedDevices()' renvoie un 'ImmutableList'. – resueman

+0

et j'ai creusé dans tous les appels de méthodes 'getConnectedDevices()' –

Répondre

1

Faire une copie de l'identifiant du périphérique connecté List. Cette copie sera 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: La collection du id doit être un Set au lieu d'une liste. Par exemple.

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

mais comment peut-il être immuable à partir de la première place? comme alors il faudrait avoir un casting de liste immuable à mutable. et j'ai cherché partout. il n'y en a pas –

+0

@EladBenda pourquoi pensez-vous que 'getConnectedDevices()' ne peut pas retourner une 'ImmutableList'? –

+0

Je vois la signature 'liste privée de getConnectedDevices() {' –

2

Vous pouvez transmettre la liste des ID de périphériques de la méthode getConnectedDevices() à une nouvelle ArrayList:

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

qui copiera toutes les valeurs de la ImmutableList dans un ArrayList à partir de laquelle vous pouvez supprimer des éléments.

L'exemple que vous avez fourni à l'aide des flux look beaucoup plus concise et compréhensible. À moins d'avoir un impact confirmé sur la performance qui n'est pas acceptable, cela semblerait être la meilleure approche.

0

De la doc java, il est dit. il ne garantit pas la mutabilité.

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

Renvoie un collecteur qui accumule les éléments d'entrée dans une nouvelle liste. Il n'y a aucune garantie sur le type, la mutabilité, la sérialisabilité ou la sécurité des threads de la liste retournée; si plus de contrôle sur la liste retournée est nécessaire, utilisez toCollection (Fournisseur). Paramètres Type: T - le type des éléments d'entrée Renvoie: un collecteur qui recueille tous les éléments d'entrée dans une liste, dans l'ordre de la rencontre.

Vous pouvez imprimer le type de liste retournée par getConnectedDevices().