2017-09-22 12 views
2

の合計値Iは、次の列ヘッダーと行を持つファイルがあります:Javaの8つのストリーム:個別のキー

CITY_NAME COUNTY_NAME POPULATION 

Atascocita Harris 65844 
Austin Travis 931820 
Baytown Harris 76335 
... 

を私はのような出力を生成しようとしたストリームを使用しています:

COUNTY_NAME CITIES_IN_COUNTY POPULATION_OF_COUNTY 
Harris 2 142179 
Travis 1 931820 
... 

これまでストリームを使用して郡名のリストを取得できましたが(これは繰り返しです)、今は別の郡の都市数を計算することに問題があります。これらの郡の都市。私はタイプtexasCitiesClassのArrayListのにファイルを読んでいると、私のコードは、これまでのようになります。この時点で

public static void main(String[] args) throws FileNotFoundException, IOException { 
    PrintStream output = new PrintStream(new File("output.txt")); 
    ArrayList<texasCitiesClass> txcArray = new ArrayList<texasCitiesClass>(); 
    initTheArray(txcArray); // this method will read the input file and populate an arraylist 
    System.setOut(output); 

    List<String> counties; 
    counties = txcArray.stream() 
      .filter(distinctByKey(txc -> txc.getCounty())) // grab distinct county names 
      .distinct() // redundant? 
      .sorted((txc1, txc2) -> txc1.getCounty().compareTo(txc2.getCounty())); // sort alphabetically 

} 

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) { 
    Map<Object, String> seen = new ConcurrentHashMap<>(); 
    return t -> seen.put(keyExtractor.apply(t), "") == null; 
}  

、私はユニーク郡の名前を含むストリームを持っています。 sorted()演算子は新しいストリームを返すので、どのようにして郡の母集団の値を得ることができますか?

+0

このコードはコンパイルされますか? 'counties'はリストですか? – nullpointer

+0

' counties = txcArray.stream().collect(Collectors.groupingBy(txc - > txc.getCounty()、Collectors.counting()));'? – Holger

答えて

1

が与えられたクラス(ctorの、ゲッター、セッター省略)が

class Foo { 
    String name; 
    String countyName; 
    int pop; 
} 

class Aggregate { 
     String name; 
     int count; 
     int pop; 
} 

あなたはCollectors.toMapを使用して集計オブジェクトにマッピングし、そのmergeFunctionを使用して、それらをマージして、あなたの値を集計できます。 TreeMapを使用すると、そのエントリはキーによって順序付けられます。

List<Foo> foos = List.of(
     new Foo("A", "Harris", 44), 
     new Foo("C", "Travis ", 99), 
     new Foo("B", "Harris", 66) 
); 

マップ

{ハリス=集合{NAME = 'ハリスで使用

TreeMap<String, Aggregate> collect = foos.stream() 
     .collect(Collectors.toMap(
       Foo::getCountyName, 
       foo -> new Aggregate(foo.countyName,1,foo.pop), 
       (a, b) -> new Aggregate(b.name, a.count + 1, a.pop + b.pop), 
       TreeMap::new) 
     ); 

、カウント= 2、POP = 110}、トラビス=集合{名前= 'Travis'、count = 1、pop = 99}}

+1

'Map counties = foos.stream().collect(Collectors.groupingBy(foo-> foo.countyName、TreeMap :: new、Collectors.summarizingInt(foo-> foo.pop))を使うことができます。 ); 'IntSummaryStatistics'にはcountとsumの両方が含まれているため、追加の' Aggregate'クラスなしですべての情報を一度に取得できます。 – Holger

+0

@Holger:まあまあですが、蓄積する価値が複数ある場合は... – user140547

関連する問題