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

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

ただいまの
回答率

88.90%

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

解決済

回答 4

投稿 編集

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

cosmosyuki

score 4

作っているプログラム

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

コードの全体

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

import java.util.Arrays;
import java.util.Collections;

class renshu19
{
    public static void main(String[] args) {

        Integer[] score = {70, 50, 80, 60, 100}; //左から1人目~5人目
        //Integer(クラス型)型の配列

        Integer[] scoreCopy;
        scoreCopy = new Integer[5];
        //配列scoreをコピーする為の配列

        System.arraycopy(score,0,scoreCopy,0,score.length);
        //値コピー

        Arrays.sort(scoreCopy,Collections.reverseOrder());
        //コピーした配列を降順でソートする

        for(int i = 0; i < score.length; i++){
            for(int j = 0; j < score.length; j++){
                if(score[i].equals(scoreCopy[j])){ //クラス型の配列の値の比較はこれ一択?
                    //score[i] == scoreCopy[j] これも成功
                    System.out.println((i+1) + "人目の順位は" + (j+1) + "位です。");
                } 
            }
        }
    }
}

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

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

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

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

まずここまで、==で比較すると、インスタンスの比較になると理解しました。
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を返すというような。

    @Override
    public boolean equals(Object x) {
        if (!(x instanceof BigDecimal))
            return false;
        BigDecimal xDec = (BigDecimal) x;
        if (x == this)
            return true;
        if (scale != xDec.scale)
            return false;
        long s = this.intCompact;
        long xs = xDec.intCompact;
        if (s != INFLATED) {
            if (xs == INFLATED)
                xs = compactValFor(xDec.intVal);
            return xs == s;
        } else if (xs != INFLATED)
            return xs == compactValFor(this.intVal);

        return this.inflated().equals(xDec.inflated());
    }


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

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

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

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+1

何故でしょう

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/15 14:36

    コメント有難うございます。
    「同じインスタンスが入っている」ということに気づきませんでした。
    System.arraycopyでコピーした際に、コピーなので中の数値が複製されて新しいscoreCopyに入っていると思っていました。別物だと思っていました。

    分かっていて使っているのであれば、==は誤りではないのですね。

    キャンセル

  • 2020/07/15 14:46

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

    インスタンスが等しいかの意図で使用する際に==を使用した方がいいかと思います。

    キャンセル

  • 2020/07/16 15:40 編集

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

    キャンセル

+1

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


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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/15 14:40

    コメント有難うございます。

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

    キャンセル

checkベストアンサー

0

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

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

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

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

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

    BigDecimal bg1 = new BigDecimal(1);
    BigDecimal bg2 = new BigDecimal(1).setScale(3);

    System.out.println(bg1);
    System.out.println(bg2);

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

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

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

    Integer in = 2;
    Integer in2 = 1 + 1;

    // 一部のIntegerは同じインスタンスが利用される
    boolean b = in == in2;
    System.out.println("in == in2 : " + b);    // true

    Integer th = 1000;
    Integer th2 = 999 + 1;

    b = th == th2;
    System.out.println("th == th2 : " + b);    // false
    b  = ((int)th == (int)th2);
    System.out.println("(int)th == (int)th2 : " + b);    // true

    b  = Integer.compare(th, th2) == 0;
    System.out.println("Integer.compare(th, th2) == 0 : " + b); // true

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/16 15:40 編集

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

    キャンセル

0

https://akrad.hatenablog.com/entry/2020/02/09/221237

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/15 13:27

    javaではメモリの意識をすることがなかなかないですが

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

    キャンセル

  • 2020/07/15 14:38

    コメント有難うございます。

    >.equals → 同一インスタンスか? = 同じメモリ領域を使用しているものか?

    そのような考え方、しっかり覚えておきます。
    リンクもとても参考になりました。有難うございます。

    キャンセル

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

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

関連した質問

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