質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.63%

JAVAでLISTの中身が書き換わってしまう

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 328

koppe

score 12

お世話になっております
皆様のお知恵を拝借できたら幸いでございます

JAVA(SpringBoot)にてファイルアップロードのシステムを作成しており動作途中で
Listの中身が書き換わってしまう事象です。

前提・実現したいこと

WEB側より複数のファイルアップロードを行い、既に登録がされているファイルを
除いた新規登録分だけを受け付ける仕組みを想定しています

発生している問題・エラーメッセージ

エラーは出ないのですが後述コード内のList変数の中身が後から登録されたデータに書き換わってしまいます

tnpFileNewdata.add(addData);

プログラム実行後のデータ
[fileName=tnpfile_03.pdf, size=700, serial=003]
[fileName=tnpfile_03.pdf, size=700, serial=003]

同じレコードが二つ出来ます

該当のソースコード

Web側から受けるデータは変数tnpListに格納
中身は3ファイル分

ファイル一つ目

kye value
alradyFlg 1
fileName tnpfile_01.pdf
fileSize 800
fileSerialNo 001

ファイル二つ目

kye value
alradyFlg 0
fileName tnpfile_02.pdf
fileSize 650
fileSerialNo 002

ファイル三つ目

kye value
alradyFlg 0
fileName tnpfile_03.pdf
fileSize 700
fileSerialNo 003

二つ目と三つ目が登録される想定です

pabulic class tnpFileBean{
    /**登録済みフラグ 0=新規登録 1=登録済み.*/
    private int alradyFlg;
    /**ファイル名.*/
    private String fileName;
    /**ファイルサイズ.*/
    private String fileSize;
    /**ファイル管理番号.*/
    private String fileSerialNo;

    public int getAlradyFlg(){
        return alradyFlg
    }
    public String getFileName(){
        return fileName
    }
    public String getFileSize(){
        return fileSize
    }
    public String getFileSerialNo(){
        return fileSerialNo
    }
//setterは略
}
    List<Map<String, Object>> tnpFileNewdata = new ArrayList<Map<String, Object>>();
        Map<String, Object> addData = new HashMap<String, Object>();
        for (tnpFileBean registTnpFile : tnpList) {
            if (registTnpFile.getAlradyFlg() == 0) {
                addData.clear();
                addData.put("fileName", registTnpFile.getBtrFilePath());
                addData.put("size", registTnpFile.getFileSize());
                addData.put("serial", registTnpFile.getFileSerialNo());
                tnpFileNewdata.add(addData);
            }
        }

補足説明

デバッグモードでステップ実行したところ
ループの初回に到達したaddの時点では
tnpFileNewdataの中身は
[fileName=tnpfile_02.pdf, size=650, serial=002]

2回目のループではaddの行に到達する前に
[fileName=tnpfile_03.pdf, size=700, serial=003]
上記に下記変わってました

参照値でもListに渡した後のList内でも変わってしまうものなのでしょうか

期待している値は
[fileName=tnpfile_02.pdf, size=650, serial=002]
[fileName=tnpfile_03.pdf, size=700, serial=003]
になります。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

回答:
同一のHashMapインスタンスに対して[clear]を行って格納情報を削除しているため。
全て別の要素にするならば、For文内で利用する都度インスタンス化しなければならない。
後蛇足ですが、JAVAの場合クラス名の1文字目は基本的に大文字にした方がいいです。

解説:
前提として、tnpList には tnpFileBean 型のインスタンスが3つ格納されているとします。

for文の外でHashMapをインスタンス化してます。

Map<String, Object> addData = new HashMap<String, Object>();

すると、HashMapのインスタンスが1つ生成されます。
コードの説明を入れますと、

  Map<String, Object> addData = new HashMap<String, Object>();
        for (tnpFileBean registTnpFile : tnpList) {
            if (registTnpFile.getAlradyFlg() == 0) {
                // addDataには2週目以降、1つ前にputメソッドで追加した内容が含まれますが、
         // 2週目の場合、tnpFileNamedataの0番目に格納したaddDataのインスタンスは
         // 同じインスタンスです。
                // そのインスタンスの格納情報をclearメソッドにてクリアします。
         // tnpFileNamedataの0番目に格納したaddDataのインスタンスは同じなので格納情報が消えます。
                addData.clear();
                addData.put("fileName", registTnpFile.getBtrFilePath());
                addData.put("size", registTnpFile.getFileSize());
                addData.put("serial", registTnpFile.getFileSerialNo());
                tnpFileNewdata.add(addData);
            }
        }


全部べつにしたければ、全て別のHashMapインスタンスを代入し直さなくてはならないので以下のような状態にしなくてはなりません。

  Map<String, Object> addData = null;
        for (tnpFileBean registTnpFile : tnpList) {
            if (registTnpFile.getAlradyFlg() == 0) {
                addData =  new HashMap<String, Object>();
                addData.put("fileName", registTnpFile.getBtrFilePath());
                addData.put("size", registTnpFile.getFileSize());
                addData.put("serial", registTnpFile.getFileSerialNo());
                tnpFileNewdata.add(addData);
            }
        }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/04 11:50

    ご回答ありがとうございます。
    無事動作いたしました。

    デバッグ中不思議だったのが変数addDataがeclipseの「変数」ビューに表示されなかったのです

    ブレークポイントを置いてaddDataの記載箇所にマウスカーソルを近づけても「Map<String, Object> addData ~(以下略)」と表示され、実際に入っているはずの値が確認できませんでした。

    今回 Map<String, Object> addData = null; を通過したところで変数ビューにも表示されるようになり、正常に動作いたしました

    本当に助かりました。
    ありがとうございました。

    キャンセル

+3

変数の内容が上書きされてしまっています。

    List<Map<String, Object>> tnpFileNewdata = new ArrayList<Map<String, Object>>();
    for (tnpFileBean registTnpFile : tnpList) {
        if (registTnpFile.getAlradyFlg() == 0) {
            //addData.clear();
            Map<String, Object> addData = new HashMap<String, Object>();
            //↑同じ器を使いまわすのではなく、新たに用意しないと上書きされる
            addData.put("fileName", registTnpFile.getBtrFilePath());
            addData.put("size", registTnpFile.getFileSize());
            addData.put("serial", registTnpFile.getFileSerialNo());
            tnpFileNewdata.add(addData);
        }
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/04 11:42

    度々のご回答ありがとうございます。
    tnpListの中身はファイル3つ分それぞれの中身がはいっております

    キャンセル

  • 2019/06/04 11:50

    tnpList の中身はデバッガなどで確認されましたか?
    また解決済みになったということは、kanimaruさんの提示されたコードでは正しく動いたということでしょうか?

    キャンセル

  • 2019/06/04 11:57

    ご回答ありがとうございます
    kanimaru様のコードで正しく動作いたしました。
    tnpList の中身はデバッガで確認しましたそれぞれfor文のループごとに変化がないかどうかも監視してましたが、変わることはありませんでした。
    ただ懸念点がaddDataの中身が確認ができなかったことです。変数ビューに表示されず、ブレークポイントを置いてマウスカーソルを近づけても変数の中身が確認できませんでした

    少々不明な点が残りましたが、無事動きました。ご協力ありがとうございました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる