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

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

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

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

Q&A

解決済

2回答

3631閲覧

Comparableインターフェースの実装について

sanezane

総合スコア91

Java

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

0グッド

1クリップ

投稿2018/01/21 04:04

javaを勉強しています。
Collection.sort(); を呼ぶと本の発行日付の古い順に並び替えられるようにcompareTo()メソッドを定義するという問題ですが、解答には

public int compareTo(Book o){ return this.publishDate.compareTo(o.publishDate); }

という解答が載っています。これでなぜ古い順に並ぶのかが理解できません。
この時のthisはどなたなのでしょうか。
o.publishDateが引数のpublishDateだとわかりますが...どのpublishDateと比べているのでしょう。比べる対象一つずつ全てという理解でよいですか?
また、昇順にソートする際にcompareTo()を定義するとき、教科書には口座番号を例にとって

public int compareTo(Account obj){ if(this.number < obj.number){ return -1; } if(this.number > obj.number){ return 1; } return 0; } }

という形が記載されていてそのように覚えたのですが、この形を使ってできないのでしょうか。
そのあたりを解説して頂けたら大変助かります。
よろしくお願い致します。

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。

ご質問にある

この形を使ってできないのでしょうか。

に対しての回答を以下の例(ファイル名:Book.java )を用いて説明します。

java

1import java.text.DateFormat; 2import java.text.SimpleDateFormat; 3import java.util.Arrays; 4import java.util.Date; 5 6/** 7 * 書籍クラス 8 */ 9public class Book implements Comparable<Book> { 10 11 private String title; // タイトル 12 private Date publishDate; // 発行日 13 private int price; // 価格 14 15 public Book(String title, Date publishDate, int price) { 16 this.title = title; 17 this.publishDate = publishDate; 18 this.price = price; 19 } 20 21 public String toString() { 22 DateFormat df = new SimpleDateFormat("yyyy/MM/dd"); 23 String str = String.format("「%s」(%s) ¥%d", title, df.format(publishDate), price); 24 return(str); 25 } 26 27 public int compareTo(Book other) { 28 return(this.publishDate.compareTo(other.publishDate)); 29 } 30 31 public static void main(String[] args) throws Exception { 32 33 DateFormat df = new SimpleDateFormat("yyyy/MM/dd"); 34 35 // Book の配列を作成 36 Book[] myBooks = new Book[]{ 37 new Book("EFFECTIVE JAVA 第2版", df.parse("2014/3/11"), 3888), 38 new Book("Pythonではじめる機械学習", df.parse("2017/5/25"), 3672), 39 new Book("JavaScript Ninjaの極意", df.parse("2013/5/25"), 3672), 40 new Book("Rubyによるクローラー開発技法", df.parse("2014/8/23"), 3218) 41 }; 42 43 // ソートする 44 Arrays.sort(myBooks); 45 46 // 配列の要素を順に表示 47 for (Book b: myBooks) { 48 System.out.println(b); 49 } 50 } 51} 52

上記をコンパイル、実行すると、myBookspublishDate(発行日付)の昇順に以下が出力されます。

「JavaScript Ninjaの極意」(2013/05/25) ¥3672

「EFFECTIVE JAVA 第2版」(2014/03/11) ¥3888
「Rubyによるクローラー開発技法」(2014/08/23) ¥3218
「Pythonではじめる機械学習」(2017/05/25) ¥3672

上記のコードで、Bookクラス の compareToメソッドでは、

java

1 public int compareTo(Book other) { 2 return(this.publishDate.compareTo(other.publishDate)); 3 }

としており、ご質問にあるコードと同じように、Date型の compareToメソッドを
使っています。

上記のコードを例に使いますが、以下のご質問

・・・という形が記載されていてそのように覚えたのですが、この形を使ってできないのでしょうか。

に対しては、できます が答えです。

この形

に似せて書くと、BookcompareToメソッドは例えば以下のようなものになるでしょう。

java

1 public int compareTo(Book other) { 2 3 long thisTime = this.publishDate.getTime(); 4 long otherTime = other.publishDate.getTime(); 5 6 if (thisTime < otherTime) 7 return -1; 8 else if (thisTime > otherTime) 9 return 1; 10 else 11 return 0; 12 }

上記で、Date型の getTime() メソッドを使っていますが、
これは Dateオブジェクトが示す日時の、1970年1月1日 00:00:00 GMTからの
経過時間をミリ秒で返します。

試しに、冒頭に挙げた Book.java の compareTo を上記のように
変えて実行してみてください。同じく、日付の昇順に表示されると思います。

補足ですが、

この時のthisはどなたなのでしょうか。

とあるのですが、this の理解が曖昧であることと、 Comparableインターフェースの
compareToメソッドの実装の仕方が分からないということとは別の問題で、
前者のほうがより基礎に近い話なので、Comparable やソートといったテーマから
切り離した、よりシンプルなコードで、ご自身の this
ついての理解について確認する、新たな質問をされたほうがよろしいかと思います。

以上参考になれば幸いです。

投稿2018/01/21 06:37

編集2018/01/21 07:52
jun68ykt

総合スコア9058

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

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

umyu

2018/01/21 07:35

横レス失礼致します。SimpleDateFormatは(https://docs.oracle.com/javase/jp/8/docs/api/java/text/SimpleDateFormat.html) 同期の項目に記載されていますが、スレッドセーフではありません。今回のコードではシングルスレッドなため問題ないと思いますが、スレッドセーフでないものに対してstatic変数で宣言し同期を取らずにアクセスしている点が気になったので、コメントしました。
jun68ykt

2018/01/21 07:53

umyu さん SimpleDateFormat はスレッドセーフではないんですね。ご指摘ありがとうございます。 static にしないでローカル変数にしました。
umyu

2018/01/21 07:57

回答の編集ありがとうございました。
sanezane

2018/01/21 15:14

ご丁寧に2パターンのコードを載せていただきましてありがとうございます! -1,0,1の形で覚えていたのですがソートの内容に合わせて考えてもよいのですね。 thisの使い方についても再確認する機会となりました! 頑張ります!
jun68ykt

2018/01/21 15:20

頑張ってくださ〜い☆
guest

0

Bookクラスで宣言しているフィールドのpublishDateが何型なのか記載されていませんが(おそらくjava.util.Date型かjava.time.LocalDate型だろうと思われますが)、そのコードが正常に機能するのであれば、publishDate型のクラスがComparableインターフェイスを正しく実装しているということです。
APIドキュメントで確認してみてください。

またそのコードの「this」が何を表しているのかわからないとのことですが、Javaでは常にthisが表すのは自身のインスタンスです。つまり提示の例ではおそらくBookクラスの中にそのcompareToメソッドが書かれていると思いますが、そのBookクラスのインスタンスがthisの参照先となります。したがってコードの解釈としては自分自身(Bookインスタンス)が持つpublishDateフィールドの値と、compareToメソッドが受け取った別のBookインスタンスが持つpublishDateのフィールドを比べて結果を返しているということです。

ちなみに「Collection.sort()」ではなく「Collections.sort()」ですよね?
CollectionsクラスのsortメソッドはAPIドキュメントにあるようにComparableインターフェイスを実装しているオブジェクトを並べ替えますが、その際、sortメソッドの内部では先ほどのcompareToメソッドを呼び出して並べ替えの処理を行っています。

口座番号の例が載っていますが、そのフィールドnumberの型はおそらくint型だと思われ、基本データ型のままではcompareToメソッドを呼び出すことができないためそのようなコードになっています。int型ではなくInteger型であれば、Date型やLocalDate型と同じようにcompareToメソッドが実装されているため、this.number.compareTo(obj.number)というコードを書くことができます。
また、もちろんpublishDateの比較を自前でそのように実装することも可能ですが、すでに実装されているcompareToメソッドが利用できるのであれば、利用することが推奨されます。

投稿2018/01/21 04:38

amadablam

総合スコア402

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

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

tignear

2018/01/21 06:04

っInteger.compare(int,int);
sanezane

2018/01/21 15:16

コードの内容が不足しており大変失礼いたしました。 compareTo()の定義の中にcompareTo()メソッドがあるのが不思議だったのですがようやく慣れてきました!ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問