0

スタックフローについて少し読んだことがありますがConcurrentModificationException、実際の更新は問題ではないようです。設計の問題であるか、まだ学んでいないテクニックが必要な可能性があります。

状況の例: イテレータが位置マーカーに沿って実行されています。その後、アクションを実行してマーカーを移動できます (例: 文字列への挿入)。正確さを維持するために、現在の位置よりも大きいすべてのマーカーもシフトする必要があります。

タスク: イテレータを爆発させずに残りのマーカーを更新するにはどうすればよいですか? イテレータを更新したり、ループを中断して再開したりできますか?

次のコードは、私の作品から抜粋したものです。

 public void innerLoop(Boolean b) {
    //An Example of what I'm working with
    HashMap<String, HashSet<Integer>> map = new HashMap<String, HashSet<Integer>>() {
        {
            put("Nonce",
                new HashSet<Integer>() {

                {
                    add(1);
                    add(2);
                    add(3);
                    add(4);
                    add(5);
                }
            });
        }
    };

    //for each key
    for (String key: map.keySet()) {
        HashSet<Integer> positions = map.get(key);

        //for each integer
        for (Iterator<Integer> it = positions.iterator(); it.hasNext();) {
            Integer position = it.next();

            System.out.println("position =" + position);
            //(out of scope) decision requiring elements from the outter loops
            if (new Random().nextBoolean()&&b) {
                //shift position by +4 (or whatever)
                //and every other (int >= position)
                System.out.println("Shift " + position + " by 4");
                Integer shift = 4;
                update(position,
                       shift,
                       positions);
                it.remove();
            }
        }
    }
}

public void update(Integer current,
                   Integer diff,
                   Set<Integer> set) {

    if (set != null) {
        HashSet<Integer> temp = new HashSet<Integer>();
        for (Integer old: set) {
            if (old >= current) {
                temp.add(old);
                System.out.println(old + "Added to temp");
            }
        }

        for (Integer old: temp) {
            set.remove(old);
            System.out.println(old + "removed");
            set.add(old + diff);
            System.out.println((old + diff) + "Added");
        }
    }
}

Garrett Hall Solution で編集

 public void nestedloops() {

    HashMap<String, HashSet<Integer>> map = new HashMap<String, HashSet<Integer>>() {
        {
            put("Hello",
                new HashSet<Integer>() {

                {
                    add(5);
                    add(2);
                    add(3);
                    add(4);
                    add(1);
                    add(6);
                }
            });
        }
    };

    //for each key
    for (String key: map.keySet()) {
        ArrayList<Integer> positions = new ArrayList<Integer>(map.get(key));
        //for each integer
        for (int i = 0; i < positions.size(); i++) {
            Integer position = positions.get(i);
            System.out.println("[" + i + "] =" + position);
            //out of scope decision
            if (new Random().nextBoolean()) {
                //shift position by +4
                //and every other (int >= position)
                System.out.println("Shift after " + position + " by 4");
                Integer shift = 4;
                //Update the array
                for (int j = 0; j < positions.size(); j++) {
                    Integer checkPosition = positions.get(j);
                    if (checkPosition > position) {
                        System.out.println(checkPosition + "increased by 4");
                        positions.set(j,
                                      checkPosition + shift);
                    }
                }
            }
        }
        //Add updated Array
        map.put(key,
                new HashSet<Integer>(positions));
    }
}
4

2 に答える 2

1

最善の策はHashSet、リストに入れてインデックスを作成することです。次に、インデックスではなく要素を参照するためにインデックスを使用できますIterator。要素を削除または追加 (更新のみ) しない限り、インデックスは正しいものになります。それ以外の場合は、それを説明する必要があります。例:

ArrayList<Integer> positions = new ArrayList<Integer>(map.get(key));
for (int i = 0; i < positions.size(); i ++) {
  // updating list
  for (int j = i; i < positions.size(); j ++) {
    positions.set(j, positions.get(i) + diff);
  }
}
于 2013-10-17T13:58:32.193 に答える
0

現在の反復コードについて心配する必要がないように、元のセットをリストにコピーします。次に、二次リストを更新します (反復されません)。

理由:

  1. 元のコレクションを一度に反復して変更することはできません (を回避する方法はありませんConcurrentModificationExceptions)
  2. リスト内のアイテムをシフトするためのナイスワンライナー。

    Collections.rotate(list.subList(j, k+1), -1);
    
  3. Guavaは、一連のユーティリティメソッドである「その述語を満たす最初のインデックスを見つけてリストを変換する」を処理できるようになります。
于 2013-10-17T14:21:52.553 に答える