2011-01-19 4 views
1

나는 일반 Partition 클래스를 작성했습니다 (파티션은 파트라고하는 분리 된 하위 세트로 구성된 집합의 구분입니다). 내부적으로 이것은 Map<T,Integer>Map<Integer,Set<T>>입니다. 여기서 정수는 파트의 레이블입니다. 예를 들어 partition.getLabel(T t)은 t가 들어있는 부분의 레이블을 제공하고 partition.move(T t, Integer label)은 레이블로 레이블이 지정된 파티션으로 이동합니다 (내부적으로 두지도를 모두 업데이트합니다).removeAll이 인수에 영향을 미치는 것 같습니다.

그러나 개체 컬렉션을 새 부분으로 이동하는 방법은 작동하지 않습니다. Set.removeAll()이 인수에 영향을 미치는 것 같습니다. 나는이 문제가 ConcurrentModificationException과 같다고 생각한다. 그러나 나는 그것을 해결할 수 없다. 죄송합니다 코드는 다소 길지만 문제가있는 곳 (약 절반 정도)에 표시했습니다. 하단의 출력은 문제가 무엇인지 명확하게해야합니다. 결국 파티션이 불법 상태입니다. 내 디버거를 사용

import java.util.*; 

    public class Partition<T> { 
    private Map<T,Integer> objToLabel = new HashMap<T,Integer>(); 
    private Map<Integer,Set<T>> labelToObjs = 
     new HashMap<Integer,Set<T>>(); 
    private List<Integer> unusedLabels; 
    private int size; // = number of elements 

    public Partition(Collection<T> objects) { 
     size = objects.size(); 
     unusedLabels = new ArrayList<Integer>(); 
     for (int i = 1; i < size; i++) 
     unusedLabels.add(i); 
     // Put all the objects in part 0. 
     Set<T> part = new HashSet<T>(objects); 
     for (T t : objects) 
     objToLabel.put(t,0); 
     labelToObjs.put(0,part); 
    } 

    public Integer getLabel(T t) { 
     return objToLabel.get(t); 
    } 
    public Set<T> getPart(Integer label) { 
     return labelToObjs.get(label); 
    } 
    public Set<T> getPart(T t) { 
     return getPart(getLabel(t)); 
    } 

    public Integer newPart(T t) { 
     // Move t to a new part. 
     Integer newLabel = unusedLabels.remove(0); 
     labelToObjs.put(newLabel,new HashSet<T>()); 
     move(t, newLabel); 
     return newLabel; 
    } 
    public Integer newPart(Collection<T> things) { 
     // Move things to a new part. (This assumes that 
     // they are all in the same part to start with.) 
     Integer newLabel = unusedLabels.remove(0); 
     labelToObjs.put(newLabel,new HashSet<T>()); 
     moveAll(things, newLabel); 
     return newLabel; 
    } 
    public void move(T t, Integer label) { 
     // Move t to the part "label". 
     Integer oldLabel = getLabel(t); 
     getPart(oldLabel).remove(t); 
     if (getPart(oldLabel).isEmpty()) // if the old part is 
     labelToObjs.remove(oldLabel); // empty, remove it 
     getPart(label).add(t); 
     objToLabel.put(t,label); 
    } 
    public void moveAll(Collection<T> things, Integer label) { 
     // Move all the things from their current part to label. 
     // (This assumes all the things are in the same part.) 
     if (things.size()==0) return; 

     T arbitraryThing = new ArrayList<T>(things).get(0); 
     Set<T> oldPart = getPart(arbitraryThing); 

    // THIS IS WHERE IT SEEMS TO GO WRONG ////////////////////////// 
     System.out.println(" oldPart = " + oldPart); 
     System.out.println(" things = " + things); 
     System.out.println("Now doing oldPart.removeAll(things) ..."); 
     oldPart.removeAll(things); 
     System.out.println(" oldPart = " + oldPart); 
     System.out.println(" things = " + things); 

     if (oldPart.isEmpty()) 
     labelToObjs.remove(objToLabel.get(arbitraryThing)); 

     for (T t : things) 
     objToLabel.put(t,label); 
     getPart(label).addAll(things); 
    } 

    public String toString() { 
     StringBuilder result = new StringBuilder(); 
     result.append("\nPARTITION OF " + size + " ELEMENTS INTO " + 
     labelToObjs.size() + " PART"); 
     result.append((labelToObjs.size()==1 ? "" : "S") + "\n"); 
     for (Map.Entry<Integer,Set<T>> mapEntry : 
     labelToObjs.entrySet()) { 
     result.append("PART " + mapEntry.getKey() + ": "); 
     result.append(mapEntry.getValue() + "\n"); 
     } 
     return result.toString(); 
    } 

    public static void main(String[] args) { 
     List<String> strings = 
     Arrays.asList("zero one two three".split(" ")); 

     Partition<String> p = new Partition<String>(strings); 
     p.newPart(strings.get(3)); // move "three" to a new part 
     System.out.println(p); 

     System.out.println("Now moving all of three's part to the " + 
     "same part as zero.\n"); 
     Collection<String> oldPart = p.getPart(strings.get(3)); 
     //oldPart = Arrays.asList(new String[]{"three"}); // works fine! 
     p.moveAll(oldPart, p.getLabel(strings.get(0))); 
     System.out.println(p); 
    } 
    } 

/* OUTPUT 
PARTITION OF 4 ELEMENTS INTO 2 PARTS 
PART 0: [two, one, zero] 
PART 1: [three] 

Now moving all of three's part to the same part as zero. 

oldPart = [three] 
things = [three] 
Now doing oldPart.removeAll(things) ... 
oldPart = [] 
things = [] 

PARTITION OF 4 ELEMENTS INTO 1 PART 
PART 0: [two, one, zero] 
*/ 

답변

0

전에서 removeAll 전에 중단 점을 배치하고 (나는 의심으로) 나는 oldPart 일들이 너무 모든 요소를 ​​제거 같은 컬렉션을 수집하는 것이 클리어로 볼 수 있습니다.

+0

감사합니다. 이 수업을 해결하기 위해 내가해야 할 일을 누구나 쉽게 볼 수 있다면 매우 감사 할 것입니다. 나는 그것을 스스로 해결하려고 노력할 것이다. – Edd

0

코드가 매우 혼란 스럽지만 최대한 멀리 나가기 위해 oldPartthings은 실제로 같은 개체입니다. 이 같은 객체가 아닌가 불려 갔을 것 같은 Set.removeAll() 확실히 인수에 영향을주지 않습니다

public boolean removeAll(Collection<?> c) { 
    boolean modified = false; 

    if (size() > c.size()) { 
     for (Iterator<?> i = c.iterator(); i.hasNext();) 
      modified |= remove(i.next()); 
    } else { 
     for (Iterator<?> i = iterator(); i.hasNext();) { 
      if (c.contains(i.next())) { 
       i.remove(); 
       modified = true; 
      } 
     } 
    } 
    return modified; 
} 

업데이트 :이를 제거하는 가장 쉬운 방법은 moveAll()things의 사본을 사용하는 것입니다

방법. 사실 그러한 복사본은 이미 존재합니다.

T arbitraryThing = new ArrayList<T>(things).get(0); 

이 줄은 생성하지만 즉시 things의 사본을 삭제합니다.

ArrayList<T> thingsToRemove = new ArrayList<T>(things) 
T arbitraryThing = thingsToRemove.get(0); 

을 그리고 방법의 나머지 부분에서, thingsToRemovethings에 대한 모든 참조를 대체 : 그래서 그것을 대체하는 게 좋을 것.

+0

감사합니다. 그것들은 같은 대상이되어 설명 할 수 있습니다. 누구든지 그것을 고치기 위해 내가해야 할 일을 제안 할 수 있습니까? 나는 '사물'의 사본을 만들지 않기를 바랄 것이다. (코드를 혼란스럽게해서 죄송합니다. 더 많은 코멘트를 달았어야 했는가, 아니면 심하게 고안되었거나 잘못 쓰여졌 을까? 들여 쓰기를 해결하는 방법을 찾지 못했습니다.) – Edd

+0

@Edd 미안하지만, 코드, 원하는대로 자유롭게 작성할 수 있습니다. :) 가장 혼란스러워하는 것은 모든 것이 "목적"에 대한 힌트를 거의주지 않는 너무나 일반적인 단어 인 "부분", "레이블"또는 "사물"이라는 것입니다. 가능한 해결책으로 답변을 업데이트하겠습니다. – biziclop

+0

감사합니다. 굉장해. 나는 그것이 추상적 인 수학적 대상이기 때문에 그 단어들을 사용했다고 생각합니다. 아마 "label"보다 더 좋은 단어가있을 것입니다. – Edd

관련 문제