KEIS BLOGは株式会社ケイズ・ソフトウェアが運営しています。

KEIS BLOG

Java言語プログラミングレッスンとパーフェクトJava


Java言語プログラミングレッスン_パーフェクトJava

今日はJava言語プログラミングレッスンとパーフェクトJavaについての私の書評です。(←こう書くとなんか偉そうですね)

Java言語プログラミングレッスン 第3版(上)
Java言語プログラミングレッスン 第3版(下)
改訂2版 パーフェクトJava

この本についての印象は、『Javaの基本的な文法とJava(と言うよりオブジェクト指向ってどんなもんか)の考え方についてわりと易しめに書いてある本』です。

そのため、Javaに触れるのが初めての私でも所見ですんなりと概要を理解することができました。

まず、大まかな印象を述べるなら、『手続き型言語(具体的にはVisualBasic6.0を思い浮かべてました)に継承とインターフェースの概念を足しただけ』という感じです。Javaに対して、オブジェクト指向だから取っ付きにくいのかな、という印象を持っていたのですが特につまるところなく理解出来ました。

Java言語プログラミングレッスンは言語特性にも触れられておりますが、それに関して特に詳しく書いてあったのはパーフェクトJavaです。前半部分で出てきた話ですが参考になりかつ面白かったのは、推奨される文字連結の書き方の話です。かなり前半に出てくる話題だった気がしますけれども。。。

文字列の連結時には”+”ではなくStringBuilderクラスを使いましょう、短時間に相当数実行されるプログラムではかなりの実行速度の違いが出るよ、という内容ですのでもはや常識となっている話ですがVB6.0の知識しかない私には大変勉強になりました。

この文字連結の実行速度なのですが、実際に試してみるとすごく違いが出てびっくりしました。

具体的には以下の実験をしてみました。

【実験概要】

アルファベット一文字を10万文字連結
実行回数は100回
最終的な計測結果は平均値を採用
実行開始時間と終了時間の差分を実行時間として計測
実行環境は私のWindowsマシン(スペックはお察しなので公表しません)

実行結果はこんなかんじです。

【”+”の場合】

1 -> 5808 ms

2 -> 6344 ms

3 -> 6819 ms

4 -> 6872 ms

5 -> 6218 ms

6 -> 6394 ms

7 -> 5939 ms

8 -> 5779 ms

9 -> 6062 ms

10 -> 6285 ms

11 -> 5861 ms

12 -> 5846 ms

13 -> 6030 ms

14 -> 5984 ms

15 -> 5847 ms

16 -> 5797 ms

17 -> 5959 ms

18 -> 6757 ms

19 -> 5920 ms

20 -> 6090 ms

21 -> 5975 ms

22 -> 5868 ms

23 -> 5990 ms

24 -> 5982 ms

25 -> 5784 ms

26 -> 5868 ms

27 -> 5970 ms

28 -> 5940 ms

29 -> 5816 ms

30 -> 5846 ms

31 -> 5778 ms

32 -> 5797 ms

33 -> 5771 ms

34 -> 5728 ms

35 -> 5838 ms

36 -> 5803 ms

37 -> 5750 ms

38 -> 5738 ms

39 -> 6181 ms

40 -> 5794 ms

41 -> 5767 ms

42 -> 5780 ms

43 -> 5713 ms

44 -> 6028 ms

45 -> 6186 ms

46 -> 5956 ms

47 -> 5935 ms

48 -> 5960 ms

49 -> 6324 ms

50 -> 5769 ms

51 -> 5821 ms

52 -> 6146 ms

53 -> 6358 ms

54 -> 6270 ms

55 -> 6110 ms

56 -> 5820 ms

57 -> 5935 ms

58 -> 6326 ms

59 -> 6760 ms

60 -> 7176 ms

61 -> 6439 ms

62 -> 6777 ms

63 -> 6306 ms

64 -> 6277 ms

65 -> 6298 ms

66 -> 6069 ms

67 -> 6138 ms

68 -> 6134 ms

69 -> 6227 ms

70 -> 6123 ms

71 -> 6208 ms

72 -> 6162 ms

73 -> 6106 ms

74 -> 6424 ms

75 -> 6421 ms

76 -> 6429 ms

77 -> 6088 ms

78 -> 6040 ms

79 -> 6252 ms

80 -> 5930 ms

81 -> 6266 ms

82 -> 6463 ms

83 -> 6218 ms

84 -> 6207 ms

85 -> 6312 ms

86 -> 6857 ms

87 -> 6418 ms

88 -> 6492 ms

89 -> 6263 ms

90 -> 6635 ms

91 -> 6950 ms

92 -> 7177 ms

93 -> 6209 ms

94 -> 5995 ms

95 -> 6162 ms

96 -> 6073 ms

97 -> 6807 ms

98 -> 6614 ms

99 -> 6608 ms

100 -> 6396 ms

Avg -> 6159 ms


【StringBuilderの場合】

1 -> 12 ms

2 -> 2 ms

3 -> 1 ms

4 -> 2 ms

5 -> 1 ms

6 -> 2 ms

7 -> 2 ms

8 -> 2 ms

9 -> 2 ms

10 -> 4 ms

11 -> 2 ms

12 -> 2 ms

13 -> 2 ms

14 -> 2 ms

15 -> 2 ms

16 -> 2 ms

17 -> 2 ms

18 -> 2 ms

19 -> 3 ms

20 -> 2 ms

21 -> 2 ms

22 -> 2 ms

23 -> 2 ms

24 -> 1 ms

25 -> 1 ms

26 -> 1 ms

27 -> 1 ms

28 -> 4 ms

29 -> 2 ms

30 -> 2 ms

31 -> 2 ms

32 -> 2 ms

33 -> 2 ms

34 -> 1 ms

35 -> 1 ms

36 -> 2 ms

37 -> 2 ms

38 -> 2 ms

39 -> 1 ms

40 -> 1 ms

41 -> 1 ms

42 -> 2 ms

43 -> 2 ms

44 -> 2 ms

45 -> 2 ms

46 -> 2 ms

47 -> 1 ms

48 -> 1 ms

49 -> 2 ms

50 -> 2 ms

51 -> 2 ms

52 -> 2 ms

53 -> 1 ms

54 -> 1 ms

55 -> 2 ms

56 -> 4 ms

57 -> 1 ms

58 -> 1 ms

59 -> 2 ms

60 -> 2 ms

61 -> 2 ms

62 -> 1 ms

63 -> 1 ms

64 -> 2 ms

65 -> 2 ms

66 -> 1 ms

67 -> 2 ms

68 -> 2 ms

69 -> 1 ms

70 -> 1 ms

71 -> 2 ms

72 -> 2 ms

73 -> 2 ms

74 -> 1 ms

75 -> 1 ms

76 -> 2 ms

77 -> 2 ms

78 -> 2 ms

79 -> 2 ms

80 -> 1 ms

81 -> 1 ms

82 -> 1 ms

83 -> 1 ms

84 -> 2 ms

85 -> 4 ms

86 -> 2 ms

87 -> 2 ms

88 -> 2 ms

89 -> 1 ms

90 -> 1 ms

91 -> 2 ms

92 -> 2 ms

93 -> 2 ms

94 -> 2 ms

95 -> 2 ms

96 -> 2 ms

97 -> 1 ms

98 -> 1 ms

99 -> 2 ms

100 -> 2 ms

Avg -> 1 ms

圧倒的じゃないか、我が軍(StringBuilder)は!

まさかの速度差。6159msと1msはちょっと差が激しいですね。
どんだけ”+”を使った文字連結が遅いかっていう話です。

“+”を使うと、
その都度内部的にStringBuilderクラスのインスタンスを生成してから、append呼び出しています。
インスタンス化には非常にコストがかかるため、for文などのループ処理の中で使用してしまうと、
非常に遅くなる可能性を秘めています。

というのも、インスタンス化の処理ってやること多いんですよね。
やることが多いと、なんか大変そうな気がしませんか?

“+”と書いたことにより裏側でどんなコードが実行されているかというと、
StringBuilder strings = new StringBuilder();
ってのが実行されるわけです。

このインスタンス化という処理のステップをざっくりあげてみます。

1.”StringBulider string”の部分でメモリ領域を確保し、
2.”new StringBuilder()”の部分でコンストラクタを呼び出して初期化処理を行い、
3.”string =”の部分で生成したインスタンスの参照値を返却する

と言ったおおまかに3ステップを行っています。

たった3ステップと思うかもしれませんが、これがループの中で繰り返されるとなると
ちりも積もれば山となる、で相当なコストがかかるわけです。
※それぞれの処理について詳しい情報は、パーマネント領域、スタック領域、ヒープ領域、インスタンス化等でググると出てきます♪

で、やっとappendメソッドを呼び出します。

しかも、その後は使わなくなるのでメモリ領域を開放し、
次のループに入った時にまたステップ1からやりなおしになるわけです…。

“+”を使うか、最初からStringBuliderを使うかでものすごい違く処理を効率化できるってことです。
書き方一つでここまで実行速度が変わるとは思いませんでした。

逆に言えば、書き方一つで自分が書いたコードがそのシステムのボトルネックになり得るかもしれません。ちょっと怖いです。

まぁ、といった具合に大切な言語特性に関係する話も書いてあったりして、手続き型から移ってくる人が気が付かなさそうなことも考慮した内容となっており、この3冊はJava初学者にはなかなかおすすめな本のではないかと思います。

パーフェクトJavaは私には難しかったですが、、、他言語習得済の人には、言語特性部分を知るのにとてもいい本じゃないかと思われます。ちなみに、もし私が完全なプログラミング初心者(C言語なにそれレベル)からJavaの学習を始めるとしたら、

Head First Java 第2版 ―頭とからだで覚えるJavaの基本

を、はじめの本に選ぶと思います。(私もこれから読もうと思っています。)どーもこの本、某有名通販サイトのレビューを見ていると肩の力を抜いて読める、しかもわかりやすい本だと書いてあります。なかなか、面白そうです。

積読がたまっているのでまだ手を付けませんが、おそらく夏までには読んでると思います。その前に、わかりやすいJavaEEウェブシステム入門を読んでるかもしれませんけどね。

 

【関連記事】
日本酒 熱燗の種類
WEB系エンジニアになるために読んだ専門書一覧