2017-12-06 1 views
0

現在、私は以下のようなTupleのArrayDequeを持っています(これはクラスを持つと考えています) :タプルのより効率的なif-statementをクラス型に関連させて実装する

private ArrayDeque<Triple<Integer, Object, Class>> paramList = new ArrayDeque<>(); 

オブジェクトタイプは、int型、ブール値や、日付、時間(私の実装であるのなし)として実際のクラスなどの原始的なことができます。

今、私はリストを反復し、それがどんなクラスタイプであるかによってメソッドを呼び出すのですが、明らかにこれは面倒な修正と更新になります。例えば (stがPreparedStatementのです):

for (Triple<Integer, Object, Class> param : paramList) { 
    if(param.getMiddle() instanceof String){ 
     st.setString(parm.getLeft(),param.getMiddle()); 
    }else if(param.getMiddle() instanceof Integer){ 
     st.setInt(parm.getLeft(),param.getMiddle()); 
    } //... more class type checks doing the same thing 
} 

私はこのhttps://stackoverflow.com/a/5579385/5858208ポストに出くわしたが、それは、私は本当に多くを行うことはできません実装しましたクラスではありませんよう。

私の質問は、このアイデアを実装するための効率的でメンテナンス可能な方法はありますか?それはタプルオブジェクトにどのようなクラス型があるのか​​ということです。

+0

downvotesとそれに応じて質問を更新する理由をお知らせください –

+0

変数 'st'とは何ですか?あなたはsetと呼ばれるメソッドをオーバーロードして、それを呼び出すことで、クラスにその作業を任せます。 –

+0

私はdvをしませんでしたが、Tuple - TripleとDequeue - Dequeの異常は奇妙です。 – laune

答えて

0

Mapを作成して、コードがサポートするすべてのクラスと正しいセッターを呼び出す値ラムダ式としてキーを含むことができます。これらの線に沿って

何か:

@FunctionalInterface 
interface PSConsumer<T,U> { 
    void accept(T t, U u) throws SQLException; 
} 

private Map<Class<?>, PSConsumer<PreparedStatement, Triple<Integer, Object, Class<?>>>> setters = new HashMap<>(); 
{ 
    setters.put(String.class, (st, param) -> st.setString(param.getLeft(), (String) param.getMiddle())); 
    setters.put(Integer.class, (st, param) -> st.setInt(param.getLeft(), (Integer) param.getMiddle())); 
    // add here code for all the classes that you support 
} 

for (Triple<Integer, Object, Class<?>> param : paramList) { 
    // this will throw an NPE if param.getMiddle() returns null or it's class is not in the map: 
    setters.get(param.getMiddle().getClass()).accept(st, param); 
} 

あなたが定義を使用することができ、同様の方法で値を抽出するためには、これらを好き:

@FunctionalInterface 
interface RSExtractor<T,U,R> { 
    R apply(T t, U u) throws SQLException; 
} 
private Map<Class<?>, RSExtractor<ResultSet, Triple<Integer, Object, Class<?>>, Object>> getters = new HashMap<>(); 
{ 
    getters.put(String.class, (rs, param) -> rs.getString(param.getLeft())); 
    getters.put(Integer.class, (rs, param) -> rs.getInt(param.getLeft())); 
} 

public List<Object> get(ResultSet rs) throws SQLException { 
    List<Object> results = new ArrayList<>(); 
    for (Triple<Integer, Object, Class<?>> param : paramList) { 
     results.add(getters.get(param.getRight()).apply(rs, param)); 
    } 
    return results; 
} 

インターフェースRSExtractorは同じように見えることに注意してくださいインターフェイスjava.util.function.BiFunction。ただし、このインターフェイスでは、実装方法でSQLException

0をスローすることができます。
+0

私はJavaストリームにはまったく初心者です。この実装は、パフォーマンスの点で多かれ少なかれ効率的です。読んだり保守したりする方がずっといいですが。私はそれを行って、それがどのように行くのかを知らせます –

+0

私はちょっと質問があります、このHashmapでlamda関数がどのくらい正確に機能していますか?クラスとしてPSConsumerをオブジェクトとしていると理解していますが、ラムダ関数はaccept関数を実装していますか?もしそうなら、Javaはこれをどのように知っていますか? –

+0

@ A.A機能インタフェース(ラムダ関数で実装可能なインタフェース)は、抽象メソッド(https://stackoverflow.com/questions/17913409、https://ocpjava.wordpress)を1つだけ持たなければなりません。com/2016/04/05/java-8-functional-interfaces-sam /)を参照してください。このため、Javaコンパイラは、インタフェース内のメソッド名からラムダ式への接続を行う方法を知っています。インターフェイスに第2の(抽象的)メソッドを追加すると、それはもはや機能的なインターフェイスでなくなり、もはやラムダ式で実装することができなくなります。 –

関連する問題