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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

3665閲覧

JAVAでテキスト中の文字の登場回数を数える。

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/01/12 06:14

###前提・実現したいこと
テキスト中の<year></year>で囲まれた年数について、それぞれ何回登場したかを表示するプログラムを書きたいと思っています。
2005~2016が対象なので、それぞれに対してMapに割当し、回数をカウントした後に出力するプログラムにする予定です。
###発生している問題・エラーメッセージ

今のところ、空のテキストファイルが作成されるのみになっています。 PatternとMatcherの問題ではないと思うのですが、Mapの使い方が間違っているのでしょうか?

###該当のソースコード

java

1import java.io.*; 2import java.util.regex.Pattern; 3import java.util.HashMap; 4import java.util.Map; 5import java.util.regex.Matcher; 6 7public class CountePaper2 { 8 void dataInOut() throws IOException{ 9 String Year = "<year>(.*?)</year>"; 10 11 //パターンの作成 12 Pattern pY = Pattern.compile(Year); 13 //入力ファイルと出力ファイルの指定、読み込み 14 BufferedReader din = new BufferedReader(new FileReader("Output.txt")); 15 BufferedWriter dout = new BufferedWriter(new FileWriter("Counted.txt")); 16 17 //パターンとマッチしたらカウントを1増やす。 18 String buf; 19 Matcher mY; 20 Map<String, Integer> map = new HashMap<>(); 21 while((buf = din.readLine()) != null){ 22 mY = pY.matcher(buf); 23 if(mY.find()){ 24 if (map.containsKey(mY.group(0))) { 25 int count = map.get(mY.group(0)) + 1; 26 map.put(mY.group(0), count); 27 } else { 28 map.put(mY.group(0), 1); 29 } 30 } 31 } 32 for(int y = 2005; y <= 2016; y++){ 33 if(map.containsKey(y)){ 34 dout.write( y + " (" + map.get(y) + ")\n"); 35 } 36 } 37 din.close(); 38 dout.close(); 39 } 40 //実行 41 public static void main(String[] args){ 42 CountePaper2 t = new CountePaper2(); 43 try{ 44 t.dataInOut(); 45 }catch(IOException error) {System.out.println("IOエラー");} 46 System.out.println("動作終了"); 47 } 48}

###試したこと
課題に対してアプローチしたことを記載してください

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

java

1for (int y = 2005; y <= 2016; y++) { 2 if (map.containsKey(y)) { // <- containsKeyの引数にIntegerが渡されている 3 ... 4 } 5}

mapのキーの型がStringなのですが、containsKeyに渡すキーの型がInteger(※)になっており型が不一致なためどんな値を指定しても「一致するキーは存在しない」とみなされているのが原因です。

※: 変数yの型はintなのですがauto boxingという言語仕様によってInteger型へ自動変換されます。
本件の原因とは直接関係しません。

対処方法はキーにアクセスしている箇所の型をStringまたはIntegerに統一すればよいです。とりあえず修正箇所を少なくするなら上のコードで以下のようにint->Stringへ変換すると期待通りの結果となると思います。
if (map.containsKey(String.valueOf(y))) {

投稿2017/01/12 06:42

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/01/12 06:53 編集

Matcher.groupの部分は他の方が指定されていたので本回答から省きました。と思ったらそちらの回答に既に自分の回答と同じコメントがついてましたね・・・ map.containsKeyにStringを指定してないのにコンパイルエラーになってくれない件は標準ライブラリーのインターフェースがジェネリクスなのに引数の型がObjectになっているせいですが、こうしたインターフェースには悲しくなることがたまにあります…
退会済みユーザー

退会済みユーザー

2017/01/12 08:53

ありがとうございました!解決しました。
guest

0

ベストアンサー

おそらくMapのkeyに格納されているのが2005などの数値ではないからです。System.out.printlnなどでmY.group(0)を出力してみてください。
Matcher#groupの引数0だと<year>xxxx</year>という、マッチした文字列全体がとれます。()部分だけ欲しいなら引数は1を指定すべきです。引数は0だと全体、1以上だとn番目のカッコ部分、ということになります。

投稿2017/01/12 06:32

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KiyoshiMotoki

2017/01/12 06:37 編集

横から失礼します。 > (Matcher#groupの)引数は1を指定すべき に加えて、  for(int y = 2005; y <= 2016; y++){    if(map.containsKey(y)){      dout.write( y + " (" + map.get(y) + ")\n");    }  } 部分にも修正が必要ですね。 変数 map のキーは String型であるにも関わらず containsKey() やget() の引数に int型の変数を指定しているため、 この部分も正常に動作していませんので。
退会済みユーザー

退会済みユーザー

2017/01/12 08:53

ありがとうございました!解決しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問