2015-09-23 11 views
5

私は、データベースにjooqを照会し、その結果をストリームで後処理する組み合わせを持っています。しかし、私のコードはあまり読みにくく、簡潔ではないと感じています。私の意図をよりよく表現する方法でコードを改善するにはどうすればよいですか?collectを使用するときに複数のストリーミングを避ける方法

sql 
    .select(field("USER_NAME", String.class)) 
    .from(table("CWD_USER")) 
    .fetch() 
    .stream() 
    .map(f -> f.getValue(field("USER_NAME", String.class))) 
    .collect(Collectors.groupingBy(s -> StringUtils.split(s, "-")[0], Collectors.counting())) 
    .entrySet().stream() 
    .sorted(new java.util.Comparator<Entry<String, Long>>() { 
     @Override 
     public int compare(Entry<String, Long> o1, 
       Entry<String, Long> o2) { 
      return o2.getValue().compareTo(o1.getValue()); 
     } 
    }) 
    .forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue()))); 

最初に私はマルチストリーミングに問題があります。私はまずjooqから結果をストリームし、次に収集したマップをストリームします。また、コンパレータは目立つように見えます。確かにクラスを作ることができますが、別の解決策があるかもしれません。

+3

[ 'Map.Entry.comparingByValue(...) '](http://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html#comparingByValue--)、私はあなたがなぜあなたがあなたのコードの他の場所でラムダ式を知っていることを既に示しているように、 'Comparator'の内部クラスです。 – Holger

+1

参考のために、対応するラムダは '.sorted((o1、o2) - > o2.getValue()。compareTo(o1.getValue()))'となりました。 @Holgerを指摘してくれてありがとう。 –

+0

'私は最初にjooqから結果をストリーミングし、次に収集したマップをストリームする - いいえ。あなたはjooqから結果をストリーミングし、それを解釈します。あなたの例に示されている追加のストリームはありません。それは、いくつかの中間操作とちょうど1つの端末操作を持つ1つのストリームです。ストリームの仕組みストリームのコア機能を「回避」したい場合は、古典的なforeach/for/whileループを使用する必要があります。しかし、正直言って:それはダウングレードだろう...ストリームは非常に簡潔で美しいです - あなた自身のコードはこれを実証します。同じ機能を使用するには、ストリームを使用しないで少なくとも100行のコードが必要です。 – specializt

答えて

5

JOOQの部分については言えませんが、Stream APIの部分はうまく見えます。並べ替える前に数を知るためには、中間で収集する必要があります。このコンパレータはすでにJDKに実装されています。つまり、Map.Entry.comparingByValue()です。あなたは(逆の順序でソートするComparator.reverseOrder()パラメータを追加します)、それを使用することができます。

sql 
    .select(field("USER_NAME", String.class)) 
    .from(table("CWD_USER")) 
    .fetch() 
    .stream() 
    .map(f -> f.getValue(field("USER_NAME", String.class))) 
    .collect(Collectors.groupingBy(s -> StringUtils.split(s, "-")[0], Collectors.counting())) 
    .entrySet().stream() 
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 
    .forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue()))); 
2

これは、より複雑なクエリの大幅な簡略化されたバージョンでない限り、私はSQLにすべてのロジックを移動すると思います。 jOOQで、

SELECT PREFIX, COUNT(*) 
FROM (
    SELECT SUBSTR(USER_NAME, 1, INSTR(USER_NAME, '-') - 1) AS PREFIX 
    FROM CWD_USER 
) T 
GROUP BY PREFIX 
ORDER BY COUNT(*) 

または::(Oracleの方言を使用して)同等のSQLクエリであるあなたがの存在を知らない場合でも

sql.select(field("PREFIX", String.class), count()) 
    .from(
    select(substring(
     field("USER_NAME", String.class), 
     inline(1), 
     position(field("USER_NAME", String.class), inline("-")).sub(inline(1)) 
    ).as("PREFIX")) 
    .from(table("CWD_USER")) 
    ) 
    .groupBy(field("PREFIX", String.class)) 
    .orderBy(count()) 
    .fetch(); 
関連する問題