2012-06-27 2 views
1

Я пытаюсь сгруппировать некоторые множества в непересекающихся множествах. Например, если у меня есть эти 5 наборов:Удалить метод итератора не работает после первого вызова

[[1, 3], [2], [1, 5], [6, 8], [1, 7]]

я хочу иметь этот результат:

[[2], [6, 8], [1, 3, 5, 7]]

Вот код:

import java.util.*; 

public class SetTest { 

public static void main(String[] args) { 
    // ---- Initialisation 
    Set<Set<Integer>> groups = new LinkedHashSet<Set<Integer>>(); 
    for (int[] set : new int[][] { {1, 3 }, {2 }, {1, 5 }, {6, 8 }, {1, 7} }) { 
     Set<Integer> group = new TreeSet<Integer>(); 
     for (int i : set) { 
      group.add(i); 
     } 
     groups.add(group); 
    } 
    System.out.println(groups); 
    // ---- Grouping values in disjoint sets 
    for (Iterator<Set<Integer>> iterator = groups.iterator(); iterator.hasNext();) { 
     Set<Integer> group = iterator.next(); 
     System.out.println(String.format(" + Checking %20s in \t %s", group, groups)); 
     for (Set<Integer> other : groups) { 
      if (!group.equals(other) && !Collections.disjoint(group, other)) { 
       other.addAll(group); 
       iterator.remove(); 
       System.out.println(String.format(" - Removed %20s -> \t %s", group, groups)); 
       break; 
      } 
     } 
    } 
    System.out.println(groups); 
} 
} 

Я использую итератор над множеством, и я хочу сгруппировать 2 множества в один, удалив один из них. Однако у меня проблема с методом Iterator.remove().
Что эта программа печатает это:

[[1, 3], [2], [1, 5], [6, 8], [1, 7]] 
+ Checking    [1, 3] in  [[1, 3], [2], [1, 5], [6, 8], [1, 7]] 
- Removed    [1, 3] ->  [[2], [1, 3, 5], [6, 8], [1, 7]] 
+ Checking     [2] in  [[2], [1, 3, 5], [6, 8], [1, 7]] 
+ Checking   [1, 3, 5] in  [[2], [1, 3, 5], [6, 8], [1, 7]] 
- Removed    [1, 3, 5] ->  [[2], [1, 3, 5], [6, 8], [1, 3, 5, 7]] 
+ Checking    [6, 8] in  [[2], [1, 3, 5], [6, 8], [1, 3, 5, 7]] 
+ Checking   [1, 3, 5, 7] in  [[2], [1, 3, 5], [6, 8], [1, 3, 5, 7]] 
- Removed   [1, 3, 5, 7] ->  [[2], [1, 3, 5, 7], [6, 8], [1, 3, 5, 7]] 
[[2], [1, 3, 5, 7], [6, 8], [1, 3, 5, 7]] 

В первый раз, снимая [1, 3] работы, как и ожидалось, но остальная часть времени, он не удаляет элемент. Я думаю, это потому, что я использую addAll(), но почему это? Потому что я не вношу изменения в groups; Я только изменяю элемент внутри него (other) - и ссылка такая же, верно?

ответ

2

Элемент HashSet должен иметь стабилизатор hashCode, но вы мутируете его, когда вы перебираете внешний набор. Это не соответствует непредсказуемым, но документированным образом.

В TreeSet могут возникнуть проблемы с изменением порядка сортировки элемента посредством мутации.

+0

Похоже, что 'HashSet' имеет внутреннюю' HashMap', причем элементы набора как ключи, и это может быть причиной ... –

+1

Да, это сторона реализации причины. Тем не менее, это также задокументированное свойство всех 'Set'. Вы можете увидеть его в [Установить Javadoc] (http://docs.oracle.com/javase/6/docs/api/java/util/Set.html). –

+1

Все, что входит в какой-либо 'Set', никогда не должно быть изменено, но не должно каким-либо образом влиять на его отношение равенства или тому подобное. OP должен использовать 'List >', а не 'Set >'. (Кроме того, * nice * catch, @MarkoTopolnik, я смотрел на это некоторое время, пытаясь понять это.) –

Смежные вопросы