Hatena::Groupquoth

Lazy Tech RSSフィード

2008-12-11

空文字判定のパフォーマンス

| 11:02 | 空文字判定のパフォーマンス - Lazy Tech を含むブックマーク はてなブックマーク - 空文字判定のパフォーマンス - Lazy Tech 空文字判定のパフォーマンス - Lazy Tech のブックマークコメント

String#length()使ったほうが、速いとは思っていたが、500000件ぐらいまわして、ようやくナノ秒で差が出る程度だった。自分は、空文字使うとき、length使ったほうが若干速いかなと思っていたけど、それ程差がないのか。

テストに使ったコードは、下。

public class StringTest {

    @Test
    public void test() {

        ArrayList<String> strList = new ArrayList<String>();
        for (int i = 0; i < 500000; i++) {
            switch (i % 3) {
                case 0:
                    strList.add("");
                    break;
                case 1:
                    strList.add(null);
                    break;
                case 2:
                    strList.add("a");
                default:
                    break;
            }
        }

        final Performance<String> p1 = new Performance<String>() {
            @Override
            public void execute(String... args) {
                isEmpty(args[0]);
            }
        };

        final Performance<String> p2 = new Performance<String>() {
            @Override
            public void execute(String... args) {
                isEmpty2(args[0]);
            }
        };

        long p1Sum = 0L;
        for (String str : strList) {
            p1Sum += p1.run(str);
        }

        long p2Sum = 0L;
        for (String str : strList) {
            p2Sum += p2.run(str);
        }

        System.out.println("Performance 1: " + p1Sum + "ns");
        System.out.println("Performance 2: " + p2Sum + "ns");
    }

    private static final String EMPTY = "";

    private static final boolean isEmpty(String str) {
        return EMPTY.equals(str);
    }

    private static final boolean isEmpty2(String str) {
        return str != null && str.length() == 0;
    }

    private abstract static class Performance<T> {

        public abstract void execute(T... args);

        public long run(T... args) {
            long start = System.nanoTime();
            execute(args);
            return System.nanoTime() - start;
        }
    }
}

2008-11-06

クラスが指定のインターフェースを実装したクラスかどうか調べる

| 00:07 |  クラスが指定のインターフェースを実装したクラスかどうか調べる - Lazy Tech を含むブックマーク はてなブックマーク -  クラスが指定のインターフェースを実装したクラスかどうか調べる - Lazy Tech  クラスが指定のインターフェースを実装したクラスかどうか調べる - Lazy Tech のブックマークコメント

インターフェース引数に渡したら,その実装クラスを探し,その実装クラスのインスタンスを作成して,返すということをやるのが,思ったより面倒.

まあ,Eclipseだと,インターフェースから,実装クラスの階層を取得できているから,簡単にできるだろと思ったけど,ある程度,段階を踏まないと駄目.

  • クラス情報の一覧を取得
  • クラス情報の一覧から取得したクラスが指定したインターフェースを実装しているかどうかのチェック

一つ目に関しては,クラスパスから,指定したパッケージのクラス情報を引くメソッドを作っていたので,そのまま流用.

二つ目の,インターフェースを実装しているかどうかのチェックはClassにisImplementedみたいなメソッドがあるだろうと思ったがない….というわけで,ClassのisAnnotationやら,全部除外した上で,Class#getInterfacesでインターフェースを取得して,指定のインターフェースと一致するかどうかというのを書いた.

めんどくさいなと思いつつ,実装した後に,ClassJavadocを見なおしてたら,Class#isAssignableFromを使えば,もっと楽に書けることが判明….インターフェースと,抽象クラスは除外した上で,Class#isAssignableFromを使えばよい.

というわけで,実装したクラスかのチェックは下のような感じ.

   public static boolean isImplemented(Class<?> clazz, Class<?> intrfc) {
        if (clazz == null || intrfc == null) {
            return false;
        }
        // インターフェースを実装したクラスであるかどうかをチェック
        if (!clazz.isInterface() && intrfc.isAssignableFrom(clazz)
                && !Modifier.isAbstract(clazz.getModifiers())) {
            return true;
        }
        return false;
    }

まあ,普通は,実装クラスの命名規則を決めて,Class.forNameで,クラス情報を取得にする方がというのが楽だし,一般的なんだろうな.

2008-10-20

処理の簡易計測

| 00:42 | 処理の簡易計測 - Lazy Tech を含むブックマーク はてなブックマーク - 処理の簡易計測 - Lazy Tech 処理の簡易計測 - Lazy Tech のブックマークコメント

ActiveObjectsのTransactionの実装方法を見て,同じことをパフォーマンス測定時にも使えるなというわけで簡易計測用の匿名クラスを作ってみた.

以下,実装.

public abstract class Performance {
    
    // 計測対象の処理を実装
    public abstract void execute();
    
    // ミリ秒で計測
    public long measureInMillis(){
        long s = System.currentTimeMillis();
        execute();
        return System.currentTimeMillis() - s;
    }

    // ナノ秒で計測
    public long measureInNanos(){
        long s = System.nanoTime();
        execute();
        return System.nanoTime() - s;
    }
}

使い方下のような感じで,匿名クラスのexecuteメソッドの中で,計測したい処理を実装するだけ.あらかじめ定義した変数を計測したい処理で,使いたい場合,finalをつけなければ行けないのが,ちょっと面倒といわれば,面倒.

        final String[] a = new String[]{"a", "b"};
        final String[] b = new String[]{"c", "d", "e"};
        final String[] c = new String[]{"f","g"};
        final String[] d = null;
        
        Performance p = new Performance(){
           @Override
           public void execute() {
               ArrayUtils.add(a,b,c,d);
           }
        };
       
        for(int i = 0; i < 10; i++){
            System.out.println(p.measureInNanos() + "ns");
        }

2008-10-03

Hibernateの使い方を簡素化してみる

| 17:23 |  Hibernateの使い方を簡素化してみる - Lazy Tech を含むブックマーク はてなブックマーク -  Hibernateの使い方を簡素化してみる - Lazy Tech  Hibernateの使い方を簡素化してみる - Lazy Tech のブックマークコメント

Mr.Persisterの時と同じ要領で,キャストをいらなくしてみた.使う際は,継承して,ジェネリクスに戻したいエンティティの型を指定して使います.

ついでに,素のSQLに対して,パラメーター詰める場合も実装.CriteriaもcreateCriteriaでクラスを引数に渡すのをどうにかしたいけど,うまい対処方法が思いないなあ.

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;

public abstract class HibernateDaoBase<T> {

    @SuppressWarnings("unchecked")
    protected T read(Query query) {
        return (T) query.uniqueResult();
    }

    protected T read(Session session, String sql, Object... params) {
        Query query = session.createSQLQuery(sql).addEntity(getTypeClass());
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return read(query);
    }

    protected T read(Session session, String sql, Map<String, Object> paramMap) {
        Query query = session.createSQLQuery(sql).addEntity(getTypeClass());
        for (Entry<String, Object> entry : paramMap.entrySet()) {
            query.setParameter(entry.getKey(), entry.getValue());
        }
        return read(query);
    }

    @SuppressWarnings("unchecked")
    protected T read(Criteria criteria) {
        return (T) criteria.uniqueResult();
    }

    @SuppressWarnings("unchecked")
    protected List<T> readList(Query query) {
        return (List<T>) query.list();
    }

    @SuppressWarnings("unchecked")
    protected List<T> readList(Criteria criteria) {
        return (List<T>) criteria.list();
    }

    private Class<?> getTypeClass() {
        Type type = getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            Type[] containTypes = ((ParameterizedType) type).getActualTypeArguments();
            // 一つだけジェネリクスで型が指定されているのを想定
            return (Class<?>) containTypes[0];
        } else {
            throw new RuntimeException("実装ミス");
        }
    }
}

2008-09-12

Javaでストリームエディタ

| 16:46 |  Javaでストリームエディタ - Lazy Tech を含むブックマーク はてなブックマーク -  Javaでストリームエディタ - Lazy Tech  Javaでストリームエディタ - Lazy Tech のブックマークコメント

PipedInputStream使えば,出力のパイプ処理が出来ることを知ったので,ストリームエディタのような処理を行うメソッドを書いてみた.

文字列処理を加えれば,sedみたいな引数での処理も出来るな.

 public static InputStream editStream(InputStream input, String regex, String replacement) throws IOException {
   Pattern pattern = null;
   if(regex != null){
     pattern = Pattern.compile(regex);
   }

   PipedOutputStream pOut = new PipedOutputStream();
   PipedInputStream pIn= new PipedInputStream(pOut);
   PrintWriter out = new PrintWriter(pOut);

   String line;
   BufferedReader reader = new BufferedReader(new InputStreamReader(input));
   while ((line = reader.readLine()) != null) {
     if(pattern != null){
       out.println(pattern.matcher(line).replaceAll(replacement));
     }else{
       out.println(line);
     }
   }
   out.flush();
   input.close();
   out.close();
   return pIn;
 }