2015/9/16 追記
この記事の最後の速度比較の結論には誤りがあります。
きちんとやれば、C#の結果はもっと速いものになります。
引用元のブログの方が検証されているので、リンクをさせていただきます。
http://crapp.hatenablog.com/entry/2015/01/17/230539
大変失礼をいたしました。
~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~
お疲れ様です!きうちです♪
今日は、JavaとC#の比較についてお話します!
ちなみに自分はどちらの言語も大好きで現場経験もあります^^
Javaをご存知でC#をご存知ない方の中には結構
「はっきり言って同じだ」
ということをご存知ない方も多いかと思います。
本題に入る前にここからいきましょうか。
ではまず、HelloWorldを比較してみます。
Java。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
C#。
using System;
public class HelloWorld
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
表示方法が「System.out.println」と「Console.WriteLine」という風にクラス・メソッドが違いますが、雰囲気は一緒。
表示メソッドがstaticメソッドであるところも一緒。
Javaがjava.lang配下のクラスはをimportしなくてもいいのに対して、C#はSystemをusingしなきゃいけないところとかは違いますが、
Javaの「パッケージ」に対し、C#には「名前空間」というものがあるあたり共通しています。
ま、usingはクラスではなく名前空間を指定するんですが…。
あ、あと.NETには「メソッド名は大文字で始める」って命名ルールがあるからメソッド名が「Main」ってなってますが、字面は一緒。起動引数も一緒。
じゃあ、「1から20までの偶数の合計を計算してみます。」というと。
public class From1To20 {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 20; i++) {
if (i % 2 == 0) {
sum += i;
}
}
System.out.println(sum);
}
}
using System;
public class From1To20
{
public static void Main(string[] args)
{
int sum = 0;
for (int i = 1; i <= 20; i++)
{
if (i % 2 == 0)
{
sum += i;
}
}
Console.WriteLine(sum);
}
}
本当はこのプログラム、iの初期値を2にしてi+=2すればif文いらなくなるんですが、まあ、if文の比較も見てほしいのであえてこれで^^
変数の宣言も、整数が「int」なのも、for文の書き方もif文の書き方も剰余演算の仕方もまったく一緒です。
あ、波括弧の書き方の標準的なお作法がちょっと違うかな。
ちなみにどちらも「110」と表示されます。
どちらもC言語がご先祖様だから、こうなっているのでしょうね。
せっかくなんで、C言語での「1から20の偶数の合計」も載せておきましょうか。
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
int sum = 0;
for (i = 1; i <= 20; i++) {
if (i % 2 == 0) {
sum += i;
}
}
printf("%d\n", sum);
}
閑話休題。
実はこの前調べ物をしていて偶然発見したブログで、気になる記述を見つけました。
- なぜJavaはC#と比べて駄目なのか - 29歳からのPG/SE人生
http://crapp.hatenablog.com/entry/2013/07/04/050930
この中に、プリミティブ型(intとかdoubleとかですね)の話題があって、
「Javaではintはオブジェクト扱いではなく、ヒープメモリにも行かない」というようなお話が書かれています。
たとえばint型変数を文字列化する場合、次のように違いますね。
int a = 256;
String b = Integer.toString(a);
int a = 256;
String b = a.ToString();
C#では、数字が発生した瞬間オブジェクトとみなされますから、
String x = 1.ToString();
みたいな「Java人には気持ち悪い(笑)」書き方もできちゃいますね。
もっとも、JavaでもStringについてはこうだけど。
ところで上記記事、その項目の最後に
※ただし、仮にJavaのプリミティブ型がC#のデータ型よりも高速に機能するのであれば、この仕様は正当化されると思う。ベンチマークもないからなんとも言えんけど。
と気になることが書かれています。
そうか、ベンチマークはないのか。
では、作って検証してみよう!
と思って、作ってみました。
public class TestOfInt {
/**
* @param args
*/
public static void main(String[] args) {
int ans = 0;
long start = System.currentTimeMillis();
for(int j = 0; j < 50000; j++) {
for(int i = 1; i <= 50000; i++) {
ans += i;
}
for(int i = 1; i <= 50000; i++) {
ans -= i;
}
}
long end = System.currentTimeMillis();
System.out.println(end - start + "ms.");
}
}
using System;
using System.Diagnostics;
namespace TestOfInt
{
class Program
{
static void Main(string[] args)
{
int ans = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < 50000; j++)
{
for (int i = 1; i <= 50000; i++)
{
ans += i;
}
for (int i = 1; i <= 50000; i++)
{
ans -= i;
}
}
sw.Stop();
Console.WriteLine("{0}ms.", sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
}
上記は同じものをJavaとC#で書きました。
ある変数に1から50000までの数字を足し、しかる後に1から50000までの数字を引くということを5万回繰り返す、というシンプルかつ「すげー意味のねー」プログラムです。
まるで穴を掘って埋める作業を毎日やっているようです。
でも、動作速度を計るのには十分じゃろと。
あ、所要時間の計り方はまったく同じにはできないので、それぞれのやり方になっています。
結果ですが、
- Java : 2783ms.
- C# : 15236ms.
という結果が出ました!
使用したマシンは以下のとおり。
- CPU : Intel Core-i3 2120 3.30GHz
- MEM : 4.0GB
- OS : Windows 7 Professional SP1 (32bit)
どうやら、やはり「オブジェクトにしていない」のは伊達ではないようです。
★ ★ ★
JavaとC#には他にも「同じところ」「似たところ」や「細かく見ると違うところ」などたくさんありますが、そういう比較をしながらコーディングしてみるのもまた乙だなと思っています^^
以上、きうちでした。それではまた!
##2014/12/14 追記
C言語版の1から20の偶数の合計について、起動引数の型が間違っていたので修正しました。
##2015/9/16 追記
結論に誤りがある旨、冒頭に追記しました。