我有一个包含以下列标题的行的文件:
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 :(得分:3)
给出类(ctor,getter,setter省略)
class Foo {
String name;
String countyName;
int pop;
}
class Aggregate {
String name;
int count;
int pop;
}
您可以通过使用Collectors.toMap
将它们映射到聚合对象并使用其mergeFunction合并它们来聚合您的值。使用TreeMap,其条目按其键排序。
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)
);
使用
List<Foo> foos = List.of(
new Foo("A", "Harris", 44),
new Foo("C", "Travis ", 99),
new Foo("B", "Harris", 66)
);
地图是
{Harris = Aggregate {name ='Harris',count = 2,pop = 110},Travis = Aggregate {name ='Travis',count = 1,pop = 99}}