94435


メンバに HashMap を含むオブジェクトのクローンを生成した際に、HashMap だけがディープコピーできていません。  
ArrayList のメンバも含んでいるのですが、そちらはディープコピーできています。

どちらも新しいインスタンスを代入しているのですが...

どこか間違っていますでしょうか？  
よろしくお願いします。

クローンするクラス

[code]

    public class Progression implements Serializable, Cloneable {
    
        @PrimaryKey public long progressionId;
        public List<DegreeNotation> degreeNotations;
        public Map<Integer, Interval> modulations;
        public List<Function> functions;
        public List<String> tags;
        public List<String> notes;
    
        public Progression() {
            progressionId = System.currentTimeMillis();
            degreeNotations = new ArrayList<>();
            modulations = new HashMap<>();
            tags = new ArrayList<>();
            notes = new ArrayList<>();
        }
    
        public Map<Integer, Interval> getModulations() {
            return modulations;
        }
    
        public boolean add(DegreeNotation notation, @Nullable Interval modulationInterval) {
            degreeNotations.add(notation);
            if (modulationInterval != null) {
                modulations.put(degreeNotations.size() - 1, modulationInterval);
            }
            return true;
        }
    
        @NonNull
        @Override
        public Progression clone() {
            Progression clone = null;
            try {
                clone = (Progression) super.clone();
                
                clone.progressionId = this.progressionId;
    
                // ArrayListのディープコピー
                List<DegreeNotation> notationsList = new ArrayList<>();
                for (DegreeNotation notation : degreeNotations) {
                    notationsList.add(notation.clone());
                }
                clone.degreeNotations = notationsList;
    
                clone.functions = new ArrayList<>(functions);
    
                clone.tags = new ArrayList<>(tags);
    
                clone.notes = new ArrayList<>(notes);
    
                // HashMap のディープコピー
                Map<Integer, Interval> deepCopiedMap = new HashMap<>();
                for (Map.Entry<Integer, Interval> entry: modulations.entrySet()) {
                    deepCopiedMap.put(entry.getKey(), entry.getValue().clone());
                }
    
                // こちらも不可
                // Map<Integer, Interval> deepCopiedMap = new HashMap<>(modulations);
    
                clone.modulations = deepCopiedMap;
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return clone;
        }
    
[/code]

クローンを使用するメソッド(別クラス)

[code]

    public void addModulation(Interval interval) {
    
            Progression clone = progression.clone();
            // まだ増えていない
            Log.d(this.getClass().getSimpleName(), "addModulation() clone.modulations.size():" + clone.modulations.size());
            // true ... なぜか同じ参照になっている？
            Log.d(this.getClass().getSimpleName(), "addModulation() clone.modulations == progression.modulations : " + (clone.modulations == progression.modulations));
            // false ... ArrayList メンバは新しいインスタンスを参照できている
            Log.d(this.getClass().getSimpleName(), "addModulation() clone.degreeNotations == progression.degreeNotations : " + (clone.degreeNotations == progression.degreeNotations));
    
            // 履歴に追加
            history.push(clone);
    
            Map<Integer, Interval> modulations = progression.getModulations();
            if (modulations.containsKey(focus)) {
                modulations.replace(focus, interval);
            } else {
                modulations.put(focus - 1, interval);
            }
            Log.d(this.getClass().getSimpleName(), "addModulation() modulations.size:" + progression.modulations.size());
    
            // この時点でクローンの HashMap のサイズも増えている？
            Log.d(this.getClass().getSimpleName(), "addModulation() clone.size:" + clone.modulations.size());
            // 増えている？
            Log.d(this.getClass().getSimpleName(), "addModulation() history.peek().modulations.size:" + history.peek().modulations.size());
        }
    
    
[/code]


CC BY-SA 4.0
2023-03-02T05:39:56.407
94054
2023-04-07T05:37:51.570
2023-04-07T05:34:49.707
57360
57360
question
java
Java でオブジェクトの clone() をした際に HashMap のメンバのディープコピーができません


改めてログ出力をよく見直していたところ、HashMap をコピーする前の

clone.functions = new ArrayList<>(functions);

のところで何かしらのエラーが出ており、それによってそれより後の処理自体がされていなかったことがわかりました。  
HashMap のコピー処理をこれよりも前に移動するとうまくいきました。

大変初歩的なミスでお騒がせしてしまい申し訳ございませんでした。


CC BY-SA 4.0
2023-04-07T05:37:51.570
94435
2023-04-07T05:37:51.570
57360
94054
answer