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

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

ただいまの
回答率

88.92%

Listの中身を変更できず困っております

解決済

回答 1

投稿 編集

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

tapipi

score 13

前提・実現したいこと

list.set(list.indexOf("i"), "I");
を使用して、53番目の位置の値を変更したい。
ですが、エラー
Exception in thread "main" java.lang.NullPointerException
と指定した場所がありませんと表示されます…。
どうしたら53番目の値を変更できますか?
またリスト内に含まれる「i」を検索して、
大文字に変える方法はございませんか?

iのインデックスは53です
後ろから調べたiのインデックスは53

該当のソースコード

import java.io.*;
import java.util.*;
public class Q {
   //   「1つ以上のスペース、ピリオド、コンマ、セミコロンのどれか」という意味
   //    |は区切ったもののどれかという意味で、\.は単にピリオドです(文字列表記する都合上、バックスラッシュが2つ必要)
   private static final String SEPARATOR = "(\\s+?|\\.|,|;)";
   /**
    * データファイルを開く
    * resources/q003/data.txt
    */
   private static InputStream openDataFile() {
       //getResourceAsStreamメソッドを利用すると、リソースファイル(設定ファイルなどのこと)を簡単に読み込むことができる
       return Q.class.getResourceAsStream("data.txt");
   }
   public static void main(String[] args){
       // 集計
       //カウントには以下のMap<String, Integer>を使用
       Map<String, Integer> map = new HashMap<>();
       try (
               /*
               ファイルの読み込み main配下にあるresourcesからファイルを取得している
                FileReaderを使ってファイルを読み込む場合には、1文字読み込んでは1文字処理して、と言うのを繰り返すため、非常に効率が悪い
               */
               FileReader fr = new FileReader(Q.class.getResource("data.txt").getFile());
               /*
               ファイルの読み込み
                なぜ最初からこのクラスを使わないかというと、このクラスはFileReaderクラスを拡張する形で利用するため。
                FileReaderクラスの持つ基本機能でファイルから読み込みは行うが、
                それにBufferedReaderクラスをかぶせて使うことでまとめて読み込む機能を持てるようになる
               */
               BufferedReader br = new BufferedReader(fr)){
           /*
           テキストを1行単位で読む
           1行まとめて読むための"readLine"メソッドが用意されている。
           注意する点は、改行文字は読み込んだ文字に含まれない事
           よって1行ごとに、改行を含まないテキストを読み込んでString型の値として返す
           */
           String line;
           //テキストファイルの読み取りの箇所ではreadLine()で行を取得
           while ((line = br.readLine()) != null) {
               /*
                全て大文字に変換する。
                */
               String resultline = line.toLowerCase();
               //splitメソッドでword[]に分割して格納していく。
               String[] words = resultline.split(SEPARATOR);
               //繰り返し処理
               for (String word : words) {
                   //もしwordがからでないなら…   文字列が空かどうかを判定する – isEmptyメソッド
                   //分解後に空白1文字が残る場合に備え、単語の出現数のカウントではisEmpty()メソッドを使用
                   if (!word.isEmpty()) {
                       /*
                       containsKeyメソッドは、指定したキーが存在するか確認を行い、キーが存在する場合は「true」を返します
                       Map.containsKey(検索するキー)
                       キー→単語
                       値 →出現数
                       単語wordが与えられたときの処理は以下の考え方。 
                        単語がMapのキーに含まれている場合、出現数を加算する。
                        単語がMapのキーに含まれていない場合、以下をMapに格納する。  
                        キー   word
                        値     1
                        */
                       if (map.containsKey(word)) {
                           /*
                           要素を取り出すためにgetメソッドを使用する。 get(Object key)
                           要素を格納するためにputメソッドを使用する。 put(K key, V value)
                            */
                           int count = map.get(word) + 1;
                           map.put(word, count);
                       } else {
                           map.put(word, 1);
                       }
                   }
               }
           }
       } catch (FileNotFoundException e) {
           System.out.println("ファイルが見つかりませんでした。");
       } catch (IOException e) {
           System.out.println("読み取りに失敗しました。");
       }
       /*
       アルファベット辞書順に並び変えて出力
       条件
           * - "I"以外は全て小文字で扱う("My"と"my"は同じく"my"として扱う)  
           * - 単数形と複数形のように少しでも文字列が異れば別単語として扱う("dream"と"dreams"は別単語)
           * - アポストロフィーやハイフン付の単語は1単語として扱う("isn't"や"dead-end")
        */
       List<String> list = new ArrayList<>();
       int maxLengthOfSpelling = 0;
       for (String key : map.keySet()) {
           list.add(key);
           if (maxLengthOfSpelling < key.length()) {
               maxLengthOfSpelling = key.length();
           }
       }
       /*
       アルファベット順にソート
       "I"以外は全て小文字で扱う("My"と"my"は同じく"my"として扱う)
       Comparatorインターフェースを用いた方法ではソートするための条件をプログラマが決めることができる。
       複雑な条件でのソートやオブジェクトの並び替えを特定のルールに沿って行いたいときは、この方法を用いる
        */
       Collections.sort(list, new Comparator<String>() {
           @Override
           public int compare(String s1, String s2) {
               return s1.compareToIgnoreCase(s2);
           }
       });
       /*
       どこかのタイミングで 格納されているiを見つけ出し、
       toUpperCaseメソッドで、小文字を大文字に変換すると解決する。
       */
       System.out.println("iのインデックスは" + list.indexOf("i") + "です");
       System.out.println("後ろから調べたiのインデックスは"+list.lastIndexOf("i"));
          // list.set(list.indexOf("i"), "I");
       // 全部の値を出力
       String format = "%-" + maxLengthOfSpelling + "s= %3d";
       for (String word : list) {
           int count = map.get(word);
           //出力の回数を制限するなら、ここで if (出現させたい件数 <= count)で可能
               System.out.printf(format, word, count);
               System.out.println();
       }
   }
}


試したこと
デバッグで、listの53番目に"i"が格納されていることを確認いたしました。
なぜインデック番号53番目に入っているのに値が変更できないのでしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • momon-ga

    2020/07/02 15:21

    ちょっと意味がわからないので、ソースの修正と
    例外が発生するのか、例外が発生しないけど、期待の動作にならないのか・・・など追記ください。

    キャンセル

  • hope_mucci

    2020/07/02 15:32

    表示されたエラーメッセージをコピー&ペーストして質問文に追記してください。
    下記ヘルプをよく読んでください。勝手に要約省略すると重大な情報が欠落することが多々あります。
    https://teratail.com/help/question-tips#questionTips3-4-2

    キャンセル

  • 退会済みユーザー

    2020/08/12 22:54

    複数のユーザーから「意図的に内容が抹消された質問」という意見がありました
    解決後に編集機能を用いて質問内容を改変し関係のない内容にしたり、内容を削除する行為は禁止しています。
    投稿していただいた質問は、後に他の誰かが困ったときに助けになる情報資産になると考えるからです。
    「質問を編集する」ボタンから編集を行い、他のユーザにも質問内容が見えるように修正してください。

回答 1

checkベストアンサー

+1

あぁ。察し。

int count = map.get(word);

で、NullPointerになってるのね。
mapは小文字なのに、wordは大文字のiなので、nullになって・・・

例外は発生する行番号が出てるので、それ最初から情報出してくれれば、すぐに解決したのに。

--
対応ですが、listのキーを変更せず表示するさいに、"i"のときだけ大文字に変換するか
mapのキーを出力直前に以下のように置き換えればよいかと

map.put("I", map.get("i"));

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/03 07:22

    エスパーかとおもったらコード削除されてたのか

    キャンセル

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

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

関連した質問

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