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

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

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

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

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

2回答

1261閲覧

TreeMapがうまくソートされない

agat

総合スコア15

Java

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

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2019/01/26 15:34

編集2019/01/27 08:42

TreeMapがうまくソートされない

【入門者向けトレーニング】Javaの練習問題:知識
https://eng-entrance.com/java-question-knowledge#javaio-2
の練習問題5をそのまま実施したところ、1行目の要素(IBARAKI 水戸市)が何故か一番最後に表示されてしまいます。

回答欄1のソースコードをコピーしても、同様の表示になってしまいました。
要素自体に誤りがあるのかと思い、他の値と行位置を変更しても、1行目となった要素は常に最後に表示されてしまいます。

ソースコードの誤りではないと思いますが、HashMap固有の問題なのか、解決方法をご教示ください。

該当のソースコード

java

1import java.io.BufferedReader; 2import java.io.FileInputStream; 3import java.io.FileNotFoundException; 4import java.io.IOException; 5import java.io.InputStreamReader; 6import java.util.Map; 7import java.util.TreeMap; 8 9public class Know5_190126 { 10 11 public static void main(String[] args) { 12 // TODO 自動生成されたメソッド・スタブ 13 14 String st = "C://Users/Test/Desktop/"; 15 String file = "TextA.txt"; 16 17 try { 18 // ファイルの読み込み 19 FileInputStream fis = new FileInputStream(st + file); 20 InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); 21 BufferedReader bf = new BufferedReader(isr); 22 23 // Mapの宣言 24 Map<String, String> map = new TreeMap<String, String>(); 25 26 // 行ごとに読み込み、半角スペースで分ける 27 String text; 28 while((text = bf.readLine()) != null) { 29 String[] param = text.split(" "); 30 31 // mapへ読み込み 32 for(int i = 0; i < param.length -1; i++) { 33 map.put(param[i], param[i+1]); 34 } 35 36 } 37 38 isr.close(); 39 40 System.out.println(map); 41 42 // Mapの要素を表示 43 for(Map.Entry<String, String> e : map.entrySet()) { 44 System.out.println(e.getKey() + " : " + e.getValue()); 45 } 46 47 48 } 49 catch(FileNotFoundException fnfe) { 50 fnfe.getStackTrace(); 51 } 52 catch(IOException ioe) { 53 ioe.getStackTrace(); 54 } 55 56 } 57 58}

ContainsKeyを追記したコード

java

1import java.io.*; 2import java.util.*; 3 4public class Know5_190127 { 5 6 public static void main(String[] args) throws Exception { 7 // TODO 自動生成されたメソッド・スタブ 8 9 String st = "C://Users/Test/Desktop/"; 10 String file = "TextA.txt"; 11 12 try { 13 // ファイルの読み込み 14 FileInputStream fis = new FileInputStream(st + file); 15 InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); 16 BufferedReader bf = new BufferedReader(isr); 17 18 // Mapの宣言 19 Map<String, String> map = new TreeMap<String, String>(); 20 21 // 行ごとに読み込み、半角スペースで分ける 22 String text; 23 while((text = bf.readLine()) != null) { 24 String[] param = text.split(" "); 25 26 // mapへ読み込み 27 for(int i = 0; i < param.length -1; i++) { 28 map.put(param[i], param[i+1]); 29 } 30 31 } 32 33 isr.close(); 34 35 System.out.println(map); 36 System.out.println(map.size()); 37 38 System.out.println(map.containsKey("GUNMA")); 39 System.out.println(map.containsKey("IBARAKI")); 40 41 // Mapの要素を表示 42 for(Map.Entry<String, String> e : map.entrySet()) { 43 System.out.println(e.getKey() + " : " + e.getValue()); 44 } 45 46 47 } 48 catch(FileNotFoundException fnfe) { 49 fnfe.getStackTrace(); 50 } 51 catch(IOException ioe) { 52 ioe.getStackTrace(); 53 } 54 } 55} 56

TextA.txtの中身(jimbesさん指摘分)

IBARAKI 水戸市 TOCHIGI 宇都宮市 GUNMA 前橋市 SAITAMA さいたま市 CHIBA 千葉市 TOKYO 東京(新宿区) KANAGAWA 横浜市

試したこと

・「IBARAKI 水戸市」の変更(例:AIBARAKI 水戸市)
・行ごとの位置の変更(例:TOKYOを1行目に)

補足情報(FW/ツールのバージョンなど)

Eclipse Version: Photon Release (4.8.0)

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

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

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

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

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

swordone

2019/01/26 15:53

paiza.ioで、入力文字列は標準入力から取得するようにしてやってみましたが、再現しません。 何かしら違うコードを実行している可能性などはないでしょうか?
agat

2019/01/26 16:02

swordoneさん ありがとうございます。 画像を貼り付けましたが、コード自体はWebのコピペであることを確認しています(読み込み先のファイル指定のみ修正)。
swordone

2019/01/26 17:42

画像のコード、まだ下に何かあるようですが…?
agat

2019/01/26 17:59

自己学習として自分が考えて入力したコードを入力しています。 ただ、自身が入力したコードはすべてコメント化しているため、プログラム上は影響ないものです。 paiza.ioで記載してみましたが、エラーが吐き出されました。 こちらは何か関係しているでしょうか。 https://paiza.io/projects/e/5_au6UFTFvMzuBbxoOTwKA
agat

2019/01/26 17:59

java.io.FileNotFoundException: TOCHIGI 宇都宮市 (No such file or directory) at java.base/java.io.FileInputStream.open0(Native Method) at java.base/java.io.FileInputStream.open(FileInputStream.java:219) at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157) at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112) at Main.main(Main.java:16)
swordone

2019/01/26 18:16

要素をFileInputStreamのコンストラクタに渡してもダメでしょ
agat

2019/01/26 18:28

そちらで入力されたコードだと問題なかったとのことですが、コードを教えていただいても良いでしょうか。
jimbe

2019/01/27 07:14

TextA.txt の中身をコピペで質問にコードとして追記して頂けますか. また, 新しく TextB.txt を作り, 中身を(コピペせずに)手打ちで作って, このコードに読ませてみてください.
agat

2019/01/27 07:36

>swordoneさん 確かにリンク先の内容だと問題なく表示されていますね・・・ >jimbeさん TextA.txtの中身は貼り付けました。 手入力はやってみます。
jimbe

2019/01/27 07:53

提示されたコードとテキストファイルで試しましたが, 水戸は前橋と横浜の間に出ました.
agat

2019/01/27 08:15

>jimbeさん 手入力でTextB.txtを作成→実行でも同じ結果(IBARAKIが最後)でした。 Textファイルの1行目を空白(2行目からIBARAKIを開始)すると、想定通りの結果となりますが、jimbeさんは1行目にIBARAKIを記入されているのでしょうか。
jimbe

2019/01/27 08:20

提示いただいたものを先頭からコピペしましたので, 1行目は空いていません. もしや, 質問に提示されているコードから何か修正されましたか?
agat

2019/01/27 08:27

コメント頂いたとおり、手入力でTextB.txtを作成し読み込ませたところ、質問した内容と一致(IBARAKIが最後に表示)しました。 そのため、試行錯誤していたときに、1行目を改行のみにしたところ、想定通り(水戸が前橋と横浜の間に表示)の結果となったため、質問させていただいたものです。 そもそも要素としてカウントされているかを確認したところ、 map.size() ---> 7 となり、茨城も要素としてカウントされていること確認しました。 しかし、containKeyで検索すると、 System.out.println(map.containsKey("GUNMA")); ---> true System.out.println(map.containsKey("IBARAKI")); ---> false となりました。これは他の要素(千葉とか)を1行目に持ってきても同じようにfalseとなってしまいます。 1行目の要素が正しくこれが何か原因のようですが、コード・読み込み対象のファイルに誤りがないとすると、私の環境が悪いのでしょうか・・・
jimbe

2019/01/27 08:36

containkey で確認されたとき, 元のコードに入っている System.out.println(map); による表示は如何でしたか. "IBARAKI=水戸市" は無かったのでしょうか. その containkey の確認の入ったコードを提示頂けますか?
agat

2019/01/27 08:42

>jimbeさん 何度もありがとうございます。 先程質問文へ追記しました。 該当箇所は以下の通りです。 System.out.println(map); System.out.println(map.size()); System.out.println(map.containsKey("GUNMA")); System.out.println(map.containsKey("IBARAKI"));
agat

2019/01/27 08:43

>jimbeさん System.out.println(map); の結果は以下のとおりです。 {CHIBA=千葉市, GUNMA=前橋市, KANAGAWA=横浜市, SAITAMA=さいたま市, TOCHIGI=宇都宮市, TOKYO=東京(新宿区), IBARAKI=水戸市}
agat

2019/01/27 08:44

連投すみません。 コンソール結果全文は以下のとおりです。 {CHIBA=千葉市, GUNMA=前橋市, KANAGAWA=横浜市, SAITAMA=さいたま市, TOCHIGI=宇都宮市, TOKYO=東京(新宿区), IBARAKI=水戸市} 7 true false CHIBA : 千葉市 GUNMA : 前橋市 KANAGAWA : 横浜市 SAITAMA : さいたま市 TOCHIGI : 宇都宮市 TOKYO : 東京(新宿区) IBARAKI : 水戸市
jimbe

2019/01/27 08:46

ありがとうございます. {CHIBA=千葉市, GUNMA=前橋市, IBARAKI=水戸市, KANAGAWA=横浜市, SAITAMA=さいたま市, TOCHIGI=宇都宮市, TOKYO=東京(新宿区)} 7 true true CHIBA : 千葉市 GUNMA : 前橋市 IBARAKI : 水戸市 KANAGAWA : 横浜市 SAITAMA : さいたま市 TOCHIGI : 宇都宮市 TOKYO : 東京(新宿区) となりました
jimbe

2019/01/27 09:07

不可解です. コンパレータの動作を見てみましょう. mapの宣言のところを // Mapの宣言 Map<String, String> map = new TreeMap<String, String>(new Comparator<String>() { @Override public int compare(String o1, String o2) { System.out.println("o1'"+o1+"' compareTo o2'"+o2+"' = "+o1.compareTo(o2)); return o1.compareTo(o2); } }); に置き換えて実行してみて頂けますか?
jimbe

2019/01/27 09:09

こちらでは以下の表示になります. o1'IBARAKI' compareTo o2'IBARAKI' = 0 o1'TOCHIGI' compareTo o2'IBARAKI' = 11 o1'GUNMA' compareTo o2'IBARAKI' = -2 o1'SAITAMA' compareTo o2'IBARAKI' = 10 o1'SAITAMA' compareTo o2'TOCHIGI' = -1 o1'CHIBA' compareTo o2'IBARAKI' = -6 o1'CHIBA' compareTo o2'GUNMA' = -4 o1'TOKYO' compareTo o2'IBARAKI' = 11 o1'TOKYO' compareTo o2'TOCHIGI' = 8 o1'KANAGAWA' compareTo o2'IBARAKI' = 2 o1'KANAGAWA' compareTo o2'TOCHIGI' = -9 o1'KANAGAWA' compareTo o2'SAITAMA' = -8 {CHIBA=千葉市, GUNMA=前橋市, IBARAKI=水戸市, KANAGAWA=横浜市, SAITAMA=さいたま市, TOCHIGI=宇都宮市, TOKYO=東京(新宿区)} 7 o1'GUNMA' compareTo o2'IBARAKI' = -2 o1'GUNMA' compareTo o2'GUNMA' = 0 true o1'IBARAKI' compareTo o2'IBARAKI' = 0 true CHIBA : 千葉市 GUNMA : 前橋市 IBARAKI : 水戸市 KANAGAWA : 横浜市 SAITAMA : さいたま市 TOCHIGI : 宇都宮市 TOKYO : 東京(新宿区)
jimbe

2019/01/27 09:42

一つ思いついたのですが, TextA.txt (TextB.txt) を作成された際, どのように(どのエディタを使って)作成されましたか? UTF8 のテキストファイルには先頭に EF BB BF という( UTF16 における BOM のような)バイトデータが付くことがあります. もしこれが付いていた場合, 一行目のアルファベット部分は普通の(?)文字列とは異なっているので, containKey でも見つからず, でも表示上は同じに見え, しかも最初が EF なので アルファベットより後ろになります.
jimbe

2019/01/27 09:56

map の宣言を置き換えていただいたコードの Syste.out.print() の部分を System.out.println("o1["+Integer.toHexString(o1.getBytes()[0] & 0xff)+"]'"+o1+"' compareTo o2'"+o2+"' = "+o1.compareTo(o2)); に変えてみてください. これで TextA.txt の一行目に IBARAKI を置いた場合に o1[ef]'IBARAKI' ~ と表示されたら, テキストファイルに EF BB BF が入っていることになり, これがソート異常の原因です.
jimbe

2019/01/27 10:05

Windows7 のメモ帳で UTF8 で保存したら, EF BB BF が入っていました.
agat

2019/01/27 13:54

>jimbe 頂いた内容で実行したところ、確かに[ef]が表示されました!!! OS環境はwin10Homeで、メモ帳で記入していたのですが、読み込み元のファイル生成方法が正しくなかったということでしょうか? ***************(ご参考)実行結果****************** o1[ef]'IBARAKI' compareTo o2'IBARAKI' = 0 o1[54]'TOCHIGI' compareTo o2'IBARAKI' = -65195 o1[47]'GUNMA' compareTo o2'IBARAKI' = -65208 o1[47]'GUNMA' compareTo o2'TOCHIGI' = -13 o1[53]'SAITAMA' compareTo o2'TOCHIGI' = -1 o1[53]'SAITAMA' compareTo o2'GUNMA' = 12 o1[43]'CHIBA' compareTo o2'TOCHIGI' = -17 o1[43]'CHIBA' compareTo o2'GUNMA' = -4 o1[54]'TOKYO' compareTo o2'TOCHIGI' = 8 o1[54]'TOKYO' compareTo o2'IBARAKI' = -65195 o1[4b]'KANAGAWA' compareTo o2'TOCHIGI' = -9 o1[4b]'KANAGAWA' compareTo o2'GUNMA' = 4 o1[4b]'KANAGAWA' compareTo o2'SAITAMA' = -8
agat

2019/01/27 14:06

妻のmacbookへeclipseをインストールし、cotEditorを使用して読み込みファイルを作成、同じコードを入力して実行したところ、期待通りの結果が表示されました! やはりjimbeさんのご指摘の通り、元ファイルのバイトデータによるもののようです。
jimbe

2019/01/27 15:41

よかったです, 成功おめでとうございます. UTF16 でこういうことがあるのは覚えていたのですが, UTF8 だし...と確認していませんでした. 記憶を確認していればもっと早く解決できたはずですね... 私は昔から使っていて慣れている vim という UNIX系のクセの強いエディタを使っています. swordone さんもおそらくメモ帳は使われていないでしょうね. ではまとめて回答を書いておきますので, 解決済みお願い致します.
guest

回答2

0

ベストアンサー

コードに特に問題はありませんでしたが, 読み込みに使われたテキストファイルが UTF8 であり, Windows のメモ帳で作成(文字コード UTF8 を選んでセーブ)するとファイルの先頭に EF BB BF という BOM が書き込まれてしまっていました.
このコードは通常表示されず, しかしファイルからの読み込みでは文字列の一部として存在するため, 一行目にあった "IBARAKI" が EF+BB+BF+"IBARAKI" となっていました.
この結果, TreeMap において containsKey("IBARAKI") は false となり, ソートは 1 バイト目が EF のため他のアルファベットより大きい値となり最後尾に位置する結果となりました.

テキストファイルの作成をメモ帳では無い(BOMを書かない)エディタで作成することで, 想定した結果となりました.

投稿2019/01/27 15:56

jimbe

総合スコア12646

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

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

0

イメージ説明

投稿2019/01/26 16:00

agat

総合スコア15

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

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

swordone

2019/01/26 17:38

こういうのは回答ではなく質問編集で入れてください。
agat

2019/01/26 17:39

失礼しました。
LouiS0616

2019/01/27 06:42

画像に関しては、単にソースコードを保存していないように見えますが。 *マークって確かそうでしたよね?
agat

2019/01/27 07:48

>LouiS0616さん キャプチャのタイミングが変かも知れませんが、キャプチャしたコードの結果がコンソール画面の表示内容と一致しています。 紛らわしくすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問