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

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

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

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

Q&A

解決済

3回答

3828閲覧

toString()メソッドのうまい書き方がわかりません。

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

1グッド

0クリップ

投稿2016/08/25 14:13

簡単な単方向連結リストの実装をしてみたのですが、toStringメソッドがうまく書けないで、困っています。
どのように記述するのがベストだと思われますか?

Java

1public class Node { 2 Node next = null; 3 int data ; 4 5 public Node(int d) { 6 this.data = d; 7 } 8 9 @Override 10 public String toString() { 11 StringBuffer sb = new StringBuffer(); 12 try{ 13 while(next != null) { 14 sb.append(data); 15 next = next.next; 16 data = next.data; 17 sb.append("->"); 18 } 19 } catch (NullPointerException e) { 20 return sb.toString(); 21 } 22 return sb.toString(); 23 } 24 25 26 27 void appendToTail(int d) { 28 Node end = new Node(d); 29 Node n = this; 30 while (n.next != null) { 31 n = n.next; 32 } 33 n.next = end; 34 }

ちなみに下記のような使い方をします。

Java

1public static void main(String[] args) { 2 Node list1 = new Node(7); 3 list1.appendToTail(1); 4 list1.appendToTail(6); 5 System.out.println(list1); 6}

この実行結果は
7->6
のようになります。
私としては
7->1->6
となるのを期待しているのですが、toString文のwhile文の中でnext.nextとしているため、このような結果になってしまいます。
しかし、どのような方法が良いのでしょうか?
thisも使えないし、インスタンスを使うのも変だし、困っています。
お分かりの方、回答お願いします。

yodel👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

再帰を使わない方法

java

1public String toString() { 2 Node node = next; // 次に入れる情報置き場 3 //シングルスレッドで使うならStringBufferよりStringBuilderを使う 4 StringBuilder builder = new StringBuilder(); 5 builder.append(data); //最初にこのデータのものを入れてしまう 6 while(node != null) { 7 builder.append("->").append(node.data); 8 node = node.next; 9 } 10 return builder.toString(); 11}

再帰を使う方法

java

1public String toString() { 2 String str = String.valueOf(data); 3 if(next != null) { 4 str += "->" + next; 5 } 6 return str; 7}

文字列連結関連
Javaでは"+"による文字列連結はStringBuilder(あるいはStringBuffer)によって実装されている。つまり

java

1str += "->" + next;

は次と同じ意味である。

java

1str = new StringBuilder(str).append("->").append(next).toString();

StringBuilderのappend(Object)は、引数Objectを引数にString.valueOf(Object)を呼び出した返り値が使われる。String.valueOf(Object)の中身は

java

1//Stringクラス内 2public static String valueOf(Object o) { 3 return o == null ? "null" : o.toString(); 4}

となる(ちなみに、System.out.println()にオブジェクトを渡した際に出力する文字列を決定するのもこのメソッド)。つまり、引数オブジェクトがnullでないかぎり、引数に対してtoString()を呼び出した結果の文字列が追加される。

投稿2016/08/25 15:32

編集2016/08/26 01:31
swordone

総合スコア20649

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

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

退会済みユーザー

退会済みユーザー

2016/08/26 00:24

二つ目の方法って再帰使ってますか? メソッドの中にtoStringはないようですが。
swordone

2016/08/26 00:26 編集

文字列連結の対象にオブジェクトが来た場合、暗黙にtoString()が呼ばれます。 このような文字列連結も内部ではStringBuilderを使っているので。
退会済みユーザー

退会済みユーザー

2016/08/26 00:32

なるほど。 上記のコードでいうと、nextの部分はnext.toStringになっているということですね? 文字列連結も内部ではStringBufferを使っているとのことですが、+演算子を使っていると、それはインスタンスの再生成を意味するのではないでしょうか? StringBuilderなのですか?
swordone

2016/08/26 00:41

説明不足でした。StringBuilder(Bufferだったかな)を使ったあとtoStringで新たな文字列を生成しています。
退会済みユーザー

退会済みユーザー

2016/08/26 01:07

すいません、二番目のコードの方にStringBuilderはなくないですか?
abs123

2016/08/26 03:03

メモリ消費(GC)とか、StackOverflowErrorを考えたら、 再帰は使わない方がいいんですかねー
退会済みユーザー

退会済みユーザー

2016/08/26 06:07

通常の文字列の連結で、+演算子を使った場合はインスタンスの再生成が行われる。 文字列以外のインスタンスを使って、文字列連結を行う場合、StringBuilderが呼び出される。 ということでしょうか?
swordone

2016/08/26 06:52

Stringのドキュメントを読んでください。どちらでもStringBuilderを使います。
退会済みユーザー

退会済みユーザー

2016/08/26 07:17

回答ありがとうございました。
guest

0

こうするとシンプル。

java

1class Node { 2 Node next = null; 3 int d = 0; 4 5 public Node(int d) { 6 this.d = d; 7 } 8 9 @Override 10 public String toString() { 11 return this.d + (this.next == null ? "" : "->" + this.next.toString()); 12 } 13 14 public void appendToTail(int d) { 15 if (this.next == null) this.next = new Node(d); 16 else this.next.appendToTail(d); 17 } 18} 19

投稿2016/08/26 02:11

tkturbo

総合スコア5572

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

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

0

next を書き換えてはいけません。

Node node = this; while (node != null) { sb.append(data); if (node.next != null) { sb.append("->"); } node = node.next; }

他に再帰を使うやりかたもあります。

public String toString() { StringBuilder sb = new StringBuilder(); sb.append(data); if (next != null) { sb.append("->"); sb.append(next.toString()); } return sb.toString(); }

投稿2016/08/25 14:43

yskz44

総合スコア100

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

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

退会済みユーザー

退会済みユーザー

2016/08/26 01:13

すいません、二番目の再帰のコードだと再帰呼び出しの度にStringBuilderインスタンスが生成されてしまいませんか?
yskz44

2016/08/26 04:13

Javaでは、インスタンスは参照されなくなったら自動的になくなります。
退会済みユーザー

退会済みユーザー

2016/08/26 06:02

回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問