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

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

ただいまの
回答率

88.81%

Java のList<List<String>>で繰り返し処理をするごとに新しい要素を作る

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,033

タイトルのとおりなのですが、Hashmap<String,List<List<String>>>のデータを作ってその中に繰り返し処理を使ってList<List<String>>にkeyごとにあたらしいデータを入れていきたいのですがどのようにすればいいのかわかりません。例えば
keyが果物のとき、valueにりんご、バナナというリストが入っていて次の繰り返し時に新しくListをnew宣言して中身を空にして追加していって
keyが動物のときvalueに像、キリンと追加していくと
すべて出力するときに
果物 像、キリン
動物 像、キリンとなってしまいます。原因自体は理解していて新しくnew 宣言したvalue変数に新しいリストを追加していってもその前のmapのkeyのvalueと同じ変数であるから結局最後に追加していったvalueのリストと同じ中身になってしまってしまうんだと思います。
この場合全く新しいリストを繰り返し処理で作成して最終的に
key→果物 value→(りんご、ばなな)
key→動物 value(このvalueと↑のvalueは違う変数)→(像、キリン)とするにはどうすればいいのでしょうか

追記
問題のコードを追加しました。書き方が気持ち悪いというのは自覚しているのですが今回は見逃してください・・・

import java.io.*;
import java.lang.reflect.Array;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;



public class Test {


    public static void main(String args[]) {
         List<String> value = new ArrayList<>();
         List<List<String>> values = new ArrayList<>();
         List<String> lines = new ArrayList<>();

         HashMap<String, List<String>> tsv = new HashMap<>();
        try {
            Path path = Paths.get("test.tsv");
            lines = Files.readAllLines(path);

        } catch (IOException ie) {
            System.out.println("入出力エラーです");
        }
        Test.sort_tsv(tsv,value,values,lines);
        Test.solve(tsv,value);


    }
    public static void sort_tsv(HashMap<String, List<String>> tsv, List<String> child_value, List<List<String>> parent_value, List<String> line){
        for(int i = 0; i < line.size();i++){
            String[] split_line = line.get(i).split("\t", 0);
            if (tsv.containsKey(split_line[0])) {
                tsv.get(split_line[0]).add(split_line[1] + ":");
                tsv.put(split_line[0], tsv.get(split_line[0]));
            } else {
                parent_value.add(child_value);
                child_value.add(i, split_line[1] + ":");
                tsv.put(split_line[0], parent_value.get(parent_value.size() - 1));
            }
        }
    }
    public static void solve(HashMap<String,List<String>> tsv, List<String> child_value){
        for (String key : tsv.keySet()) {
            String val = String.join("", child_value);
            StringBuilder value_cut = new StringBuilder(val);
            value_cut.setLength(value_cut.length() - 1);
            System.out.println(key + "\t" + value_cut);
        }
    }
}
fruit    apple
fruit    banana
pet    dog
pet    cat
実行結果
fruit    apple:banana:dog:cat
pet    apple:banana:dog:cat
想定実行結果
fruit    apple:banana
pet      dog:cat
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • azuapricot

    2019/08/07 16:51

    文章だけじゃ何が言いたいか全くわからないので、実コードを提示して下さい。

    キャンセル

  • BluOxy

    2019/08/07 16:52

    map.put("果物",りんごやバナナのリスト);
    map.put("動物",像やキリンのリスト);
    では駄目なんでしょうか。

    また、該当のコードを見せて頂けると状況が分かりやすいと思います。

    キャンセル

  • m.ts10806

    2019/08/07 17:26

    >書き方が気持ち悪いというのは...
    それは見た人が感じることであって自己弁護のように入れておく必要はないと思います。
    質問内容に必要なのはあくまで要件と問題と再現できるコードなので。

    キャンセル

回答 2

checkベストアンサー

+2

一見不必要に見える処理を排除してコードを書きました。
質問内容を解決するための処理は実装されています。
(デバッグはしていないため、参考程度に留めてください)

また、命名も直しました。
(単数形なのか複数形なのかが分からず、メソッド名から中の処理が想像できなかったため)

import java.io.*;
import java.lang.reflect.Array;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class Test {
    public static void main(String args[]) {
        List<String> lines = new ArrayList<>();
        try {
            Path path = Paths.get("test.tsv");
            lines = Files.readAllLines(path);
        } catch (IOException ie) {
            System.out.println("入出力エラーです");
        }

        HashMap<String, List<String>> tsvMap = createTsvAsMap(lines);
        display(tsvMap);
    }

    public static HashMap<String, List<String>> createTsvAsMap(List<String> lines){
        HashMap<String, List<String>> tsvMap = new HashMap<>();
        for(String line : lines){
            String[] elements = line.split("\t", 0);
            if (!tsvMap.containsKey(elements[0])) {
                List<String> values = new ArrayList<>();
                tsvMap.put(elements[0], values);
            }
            tsvMap.get(elements[0]).add(elements[1]);
        }
        return tsvMap;
    }

    public static void display(HashMap<String,List<String>> tsvMap){
        for (Entry<String, List<String>> entry : tsvMap.entrySet()) {
            System.out.println(entry.getKey() + "\t" + String.join(":",key.getValue()));
        }
    }
}

やっていることは至極単純で、下記のようにHashMapを作成しています。

  1. 読み込んだtsvの1列目をキー、2列を値として読込む
  2. そのキーがまだHashMapに存在しない場合はリストのインスタンスを作成し、putする
  3. キーが存在する場合はHashMapからそのキーを元にgetして、リストに値をaddする

余談ですが、表示するときはString.joinを使って:を連結文字として扱うと短くコードが書けます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/07 17:48

    ありがとうございます!
    HashMap<String, List<String>> tsvMap = createTsvAsMap(lines);と
    public static HashMap<String, List<String>> createTsvAsMap(List<String> lines)
    が今まで見たことがない書き方だったのでいまいちよくわからないです。これはどういった文法なのでしょうか?

    キャンセル

  • 2019/08/07 17:56

    「Java メソッド 戻り値」で調べてみてください。

    >public static HashMap<String, List<String>> createTsvAsMap(List<String> lines)

    元々のコードではsort_tsv、solveというメソッドがありますが、戻り値はなし(void)になっています。
    それをやめて、戻り値を「HashMap<String, List<String>>」のオブジェクトで返すように変更しました。

    上記のような実装をしたとき、createTsvAsMapメソッドを呼び出す際は
    >HashMap<String, List<String>> tsvMap = createTsvAsMap(lines);
    と書くことができます。

    このように呼び出すと、createTsvAsMapメソッドの戻り値をtsvMapに渡すことができます。

    キャンセル

  • 2019/08/07 18:06 編集

    実装の不明点を答えるとは言いましたが、語弊がありました。
    Javaの構文・作法についてはこの質問の範疇外になるので、調べるかまた別の質問を立ててください。

    私の書いたコードがどのようにして下記要件を満たしたのか分からない場合はお答えします。
    >Hashmap<String,List<List<String>>>のデータを作ってその中に繰り返し処理を使ってList<List<String>>にkeyごとにあたらしいデータを入れていきたい

    キャンセル

+1

key→果物 value→(りんご、ばなな)

であれば、

Map<String, List<String>> 


で十分ではないかと思います。 

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

同じタグがついた質問を見る