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

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

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

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

Q&A

解決済

4回答

3001閲覧

【Java】Integer型 配列変数の値同士の比較方法について

cosmosyuki

総合スコア4

Java

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

1グッド

0クリップ

投稿2020/07/15 04:16

編集2020/07/16 15:22

作っているプログラム

5人の生徒がいて、1人目から順に「○番目のテストの順位は□位です」と表示するプログラムを書いています。テストの点数は、Integer型の配列変数に格納しており、その配列のコピーを降順でソートしたものと比較して順位を出しています。
クラス型配列同士の値の比較方法について確認したいことがありますので宜しくお願い致します。

コードの全体

これがコードの全体です。
問題は下部にあるネストされたfor文の中の、if文の条件です。
詳細は該当のソースコードをご覧ください。

java

1import java.util.Arrays; 2import java.util.Collections; 3 4class renshu19 5{ 6 public static void main(String[] args) { 7 8 Integer[] score = {70, 50, 80, 60, 100}; //左から1人目~5人目 9 //Integer(クラス型)型の配列 10 11 Integer[] scoreCopy; 12 scoreCopy = new Integer[5]; 13 //配列scoreをコピーする為の配列 14 15 System.arraycopy(score,0,scoreCopy,0,score.length); 16 //値コピー 17 18 Arrays.sort(scoreCopy,Collections.reverseOrder()); 19 //コピーした配列を降順でソートする 20 21 for(int i = 0; i < score.length; i++){ 22 for(int j = 0; j < score.length; j++){ 23 if(score[i].equals(scoreCopy[j])){ //クラス型の配列の値の比較はこれ一択? 24 //score[i] == scoreCopy[j] これも成功 25 System.out.println((i+1) + "人目の順位は" + (j+1) + "位です。"); 26 } 27 } 28 } 29 } 30}

該当のソースコード・疑問点

クラス型配列同士の比較なので、ルール通りに行うと score[i].equals(scoreCopy[j]) での比較になると思うのですが、初め、私はコメントのように score[i] == scoreCopy[j] としてしまったのですが、これでも成功しました。 何故でしょう、このように行うことは良くないでしょうか。ルール外になりますか。

java

1 if(score[i].equals(scoreCopy[j])){ //オブジェクト型の配列の値の比較はこれ一択? 2 //score[i] == scoreCopy[j] これでも成功 3 System.out.println((i+1) + "人目の順位は" + (j+1) + "位です。"); 4 }

【追記】皆さんのご回答をもとに、少し調べた内容

まずここまで、==で比較すると、インスタンスの比較になると理解しました。
System.arraycopyでは中身をコピーしたが、Integer型の配列なので、値が格納されているメモリの場所をコピーしている事になって、結果としてコピーしたものはコピー元と同じオブジェクトを指しているという事。
そして、momon-ga様が二つ目に示して頂いたコードの中のように、intでキャストして比較ができるという事。

ただ、疑問に思った事。
momon-ga様が最初に示して頂いたコードの、下から2行目の結果がfalseになる事が疑問でした。

System.out.println(bg1.equals(bg2));  //false

System.out.println(bg1.compareTo(bg2) == 0); //true

これについて調べていった結果、equalsメソッドは、BigDecimalクラスでオーバーライドされていて、
(Integerクラスや、Stringクラスでもされていました。他にもあるかもしれません)

以下のように記述されており、上から三つ目のifのところが該当の箇所だと思われます。
スケール値が違うとfalseを返すというような。

java

1 @Override 2 public boolean equals(Object x) { 3 if (!(x instanceof BigDecimal)) 4 return false; 5 BigDecimal xDec = (BigDecimal) x; 6 if (x == this) 7 return true; 8 if (scale != xDec.scale) 9 return false; 10 long s = this.intCompact; 11 long xs = xDec.intCompact; 12 if (s != INFLATED) { 13 if (xs == INFLATED) 14 xs = compactValFor(xDec.intVal); 15 return xs == s; 16 } else if (xs != INFLATED) 17 return xs == compactValFor(this.intVal); 18 19 return this.inflated().equals(xDec.inflated()); 20 } 21

Integerクラスも確認したところ、オブジェクト同士の確認もするが
Integerクラス同士のオブジェクトの比較の際には、中の値を比べてくれるコードが記述されていました。

なので、Integerクラスにおいて、オブジェクト同士が同値であるかどうか確認したい場合は
(Integerクラス内でオーバーライドした)equalsメソッドを使う、で大丈夫だと思いました。

長々と申し訳ありません。皆様ありがとうございました。

momon-ga👍を押しています

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

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

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

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

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

guest

回答4

0

java

1Object a = new Object(); 2Object b = a; 3System.out.println(a == b);

これがtrueになるのと同じ理屈です。

投稿2020/07/15 04:34

swordone

総合スコア20651

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

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

cosmosyuki

2020/07/15 05:40

コメント有難うございます。 同じオブジェクトを指しているという事に気づきませんでした。 分かりやすいサンプルコードを有難うございます。
guest

0

何故でしょう

Javaで==をオブジェクトに対して行うと、インスタンスが等しいかの比較になります。両者は並べ替えただけで、同じインスタンスが入っている以上、==で比較しても正しい結果を得られます。

投稿2020/07/15 04:20

maisumakun

総合スコア145184

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

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

cosmosyuki

2020/07/15 05:36

コメント有難うございます。 「同じインスタンスが入っている」ということに気づきませんでした。 System.arraycopyでコピーした際に、コピーなので中の数値が複製されて新しいscoreCopyに入っていると思っていました。別物だと思っていました。 分かっていて使っているのであれば、==は誤りではないのですね。
退会済みユーザー

退会済みユーザー

2020/07/15 05:46

誤りではないですね。 が、厳密にいえばインスタンスが等しいかの意図で比較を行っているわけではないので やはり.equalsが正しいと思われますよ。 インスタンスが等しいかの意図で使用する際に==を使用した方がいいかと思います。
cosmosyuki

2020/07/16 06:41 編集

遅くなり申し訳ありません。追記しました。色々有難うございました。
guest

0

ベストアンサー

==で比較しても問題ないのは、他の方の回答と同じなので割愛して

このように行うことは良くないでしょうか。ルール外になりますか。

について、わかっていれば(同一インスタンスを比較する)問題ないと思います。
一部のIntegerインスタンスは、共有されるは知っていて損はないですが、今回の件とは関係ありません。

ルール外というか気になったのは数値の比較をequalsでやるものという点です。

以下は、1という数字の比較ですがequalsでは期待通りになりません。
sysoutの結果を見れば、違いはわかると思います。

java

1 BigDecimal bg1 = new BigDecimal(1); 2 BigDecimal bg2 = new BigDecimal(1).setScale(3); 3 4 System.out.println(bg1); 5 System.out.println(bg2); 6 7 System.out.println(bg1.equals(bg2)); 8 System.out.println(bg1.compareTo(bg2) == 0);

Integerなので、scale無いのですが比較を必ずequalsでやるものと覚えてしまうと
意図しない結果になることがあるかもしれません。

==の比較が使える場面では、私は積極的に使った方がよいと考えます。
とはいえ、==比較でバグを埋め込みやすいのは事実なので、使える場面を見極める必要があります。

java

1 Integer in = 2; 2 Integer in2 = 1 + 1; 3 4 // 一部のIntegerは同じインスタンスが利用される 5 boolean b = in == in2; 6 System.out.println("in == in2 : " + b); // true 7 8 Integer th = 1000; 9 Integer th2 = 999 + 1; 10 11 b = th == th2; 12 System.out.println("th == th2 : " + b); // false 13 b = ((int)th == (int)th2); 14 System.out.println("(int)th == (int)th2 : " + b); // true 15 16 b = Integer.compare(th, th2) == 0; 17 System.out.println("Integer.compare(th, th2) == 0 : " + b); // true 18

投稿2020/07/15 06:17

編集2020/07/15 06:53
momon-ga

総合スコア4820

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

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

cosmosyuki

2020/07/16 06:41 編集

遅くなり申し訳ありません。追記しました。色々有難うございました。
guest

0

投稿2020/07/15 04:24

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2020/07/15 04:27

javaではメモリの意識をすることがなかなかないですが .equals → 同一インスタンスか? = 同じメモリ領域を使用しているものか? ということです。
cosmosyuki

2020/07/15 05:38

コメント有難うございます。 >.equals → 同一インスタンスか? = 同じメモリ領域を使用しているものか? そのような考え方、しっかり覚えておきます。 リンクもとても参考になりました。有難うございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問