Collectors的俩个作用:
1、将数据流缩减为一个单一值,可以是一个collection、基本数据类型或者一个自定义对象;
2、将数据流中的元素进行分组,根据任务类型将流中所有的任务进行分组。这将产生一个Map
3、分割一个流中的元素,将一个流分割为两组。
规约(缩减stream)
规约成一个列表
List stringList = list.stream().map(Person::getName).collect(toList());
规约到一个set,toCollection可以指定收集器的实现类型
Set personSet = list.stream().collect(toSet());
HashSet personHashSet = list.stream().collect(toCollection(HashSet::new));
规约到一个map,toMap第一个参数是key,第二个参数为value,第三个参数为key相同时的解决方案,这里取后面的key
Map hashMap =
list.stream().collect(toMap(Person::getType, Person::getName, (x, y) -> y));
hashMap.forEach((k, v) -> System.out.println(k + "-" + v));
找到type最大的person
Person person6 = list.stream().collect(collectingAndThen(maxBy((p1, p2) -> p1.getType() - p2.getType()), Optional::get));
统计type总数
int sum = list.stream().collect(summingInt(Person::getType));
连接string流,以-连接
String nameStr = list.stream().map(Person::getName).collect(joining("-"));
分类收集:
groupingBy根据指定属性分组
List list = new ArrayList();
for (int i = 0; i < 2; i++) {
list.add(new Person("李雷", i));
list.add(new Person("小明", i));
}
// groupingBy根据指定属性分组
Map> map = list.stream().collect(groupingBy(Person::getName));
map.forEach((k, v) -> System.out.println(k + "-" + v));
// 加个参数指定分组后的类型
Map> map2 = list.stream().collect(groupingBy(Person::getName, toSet()));
// 聚合操作
// 分组后value取集合的size
Map map3 = list.stream().collect(groupingBy(Person::getName, counting()));
map3.forEach((k, v) -> System.out.println(k + "-" + v));
// 分组后value取集合的和
Map map4 =
list.stream().collect(partitioningBy(Person::isStudent, summingInt(Person::getType)));
map4.forEach((k, v) -> System.out.println(k + "-" + v));
// 分组后,value取分组后最大的person
Map> map5 = list.stream()
.collect(groupingBy(Person::getName, maxBy(Comparator.comparing(Person::getType))));
map5.forEach((k, v) -> System.out.println(k + "-" + v));
// 分组,取type Set
Map> map6 =
list.stream().collect(groupingBy(Person::getName, mapping(Person::getType, toSet())));
map6.forEach((k, v) -> System.out.println(k + "-" + v);
根据条件分成两组
Map> map1 =
list.stream().collect(partitioningBy(person -> person.getName().equals("小明")));
自定义收集器
public class MultisetCollector implements Collector, Multiset> {
@Override
public Supplier> supplier() {
return HashMultiset::create;
}
@Override
public BiConsumer, T> accumulator() {
return (set, e) -> set.add(e, 1);
}
@Override
public BinaryOperator> combiner() {
return (set1, set2) -> {
set1.addAll(set2);
return set1;
};
}
@Override
public Function, Multiset> finisher() {
return Function.identity();
}
@Override
public Set characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
public static void main(String[] args) {
Stream stream = Stream.of("shekhar", "rahul", "shekhar");
// Multiset可以把重复元素存入的set
Multiset set = stream.collect(new MultisetCollector<>());
set.forEach(str -> System.out.println(str + ":" + set.count(str)));
}
}
文本的字数统计
public static void wordCount(Path path) throws IOException {
// 字数统计,读取文件,文件类型是 ANSI(GBK)
Map wordCount = Files.lines(path, Charset.forName("GBK")).parallel()
.flatMap(line -> Arrays.stream(line.trim().split("\\s")))// 将每行字符串按空格拆分,并合并成一个字符串流,每一个元素是一个单词
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())//将不是英文字母的过滤掉
.filter(word -> word.length() > 0).map(word -> new AbstractMap.SimpleEntry<>(word, 1))//过滤空格符,转换成SimpleEntry对象
.collect(groupingBy(AbstractMap.SimpleEntry::getKey, counting()));//根据key(即单词)分组,记录每个单词出现的次数
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
System.out.println("sum: " + wordCount.values().stream().collect(summingInt(Long::intValue)));
}
public class CollectorsTest {
public static void main(String[] args) {
// testCollect();
// testJuHeGuiYue();
// testGroupingBy();
testCollectingAndThen();
}
/**
* 数据收集
*/
public static void testCollect() {
Stream iStream = Stream.of(1, 3, 2, 4, 6, 5);
// toList,默认指定收集器为ArrayList
List l = iStream.collect(toList());
iStream = Stream.of(1, 3, 2, 4, 6, 5);
Set iSet = iStream.collect(toSet());
// 收集成list或set
testToCollection();
// 收集成Map
testToMap();
}
/**
* 聚合规约
*/
public static void testJuHeGuiYue() {
testJoining();
testReducing();
}
/**
* toMap转换成HashMap,串行收集 toConcurrentMap转换成ConcurrentHashMap,并发收集
* 第一个参数:key的收集方式
* 第二个参数:value的收集方式
* 第三个参数:key重复时value的处理方式 第四个参数:自定义收集Map
*/
public static void testToMap() {
Stream voStream = getStream();
// toMap,收集为HashMap,第一个参数,key生成,第二个参数,value生成;Function.identity()返回自身
Map map = voStream.collect(toMap(StudentVo::getId, Function.identity()));
System.out.println(map);
voStream = getStream();
Map map1 = voStream.collect(toMap(StudentVo::getId, StudentVo::getName));
// 并发收集
voStream = getStream();
Map map2 =
voStream.collect(toConcurrentMap(StudentVo::getId, StudentVo::getName));
System.out.println(map2);
voStream = getStream();
// key重复,后面覆盖前面的
Map map4 = voStream
.collect(toMap(StudentVo::getId, StudentVo::getName, (s, s2) -> s2, LinkedHashMap::new));
System.out.println(map4);
voStream = getStream();
// key重复,取两者间大的那个
Map map5 = voStream.collect(toMap(StudentVo::getId, StudentVo::getName,
BinaryOperator.maxBy(Comparator.comparing(Function.identity()))));
System.out.println(map5);
}
/**
* toCollection 转换成list或Set,可以自定义收集器
*/
public static void testToCollection() {
Stream iStream = Stream.of(1, 3, 2, 4, 6, 5);
// toCollection,可以自定义收集器
List l = iStream.collect(toCollection(LinkedList::new));
iStream = Stream.of(1, 3, 2, 4, 6, 5);
Set set = iStream.collect(toCollection(TreeSet::new));
System.out.println(set);
iStream = Stream.of(1, 3, 2, 4, 6, 5);
}
/**
* 拼接 第一个参数:拼接字符 第二个参数:前缀 第三个参数:后缀
*/
public static void testJoining() {
// list元素必须为String
String s = Stream.of("1", "3", "2", "4", "6", "5").collect(joining());
String s1 = Stream.of("1", "3", "2", "4", "6", "5").collect(joining(","));
String s2 = Stream.of("1", "3", "2", "4", "6", "5").collect(joining(",", "[", "]"));
System.out.println(s);
System.out.println(s1);
System.out.println(s2);
}
/**
* 规约,和Stream中的reduce操作样,但是Stream中的开销更小
* 第一个参数:设置流没有元素的时候的初始值
* 第二个参数:流的转换方式,也可以是规约方式
* 第三个参数:流的规约方式
*/
public static void testReducing() {
Stream voStream = getStream();
long l = voStream.collect(reducing(0L, StudentVo::getId, Long::sum));
System.out.println(l);
voStream = getStream();
long ll = voStream.map(StudentVo::getId).collect(reducing(0L, Long::sum));
System.out.println(ll);
voStream = getStream();
long l1 = voStream.reduce(0L, (aLong, studentVo) -> studentVo.getId(), Long::sum);
System.out.println(l1);
voStream = getStream();
long l2 = voStream.map(StudentVo::getId).reduce(0L, Long::sum, Long::sum);
System.out.println(l2);
}
/**
* 分组
* 第一个参数:指定分组的key
* 第二个参数:指定分组后收集的Map类型,默认为HashMap
* 第三个蚕食:指定Value的转换方式,默认为Function.identity()
*/
public static void testGroupingBy() {
Stream voStream = getStream();
Map> listMap = voStream.collect(groupingBy(StudentVo::getId));
System.out.println(listMap);
voStream = getStream();
Map> setMap = voStream.collect(groupingBy(StudentVo::getId, toSet()));
System.out.println(setMap);
voStream = getStream();
//mapping可以自定义要收集的字段
Map> listMap1= voStream.collect(groupingBy(StudentVo::getId, HashMap::new, mapping(StudentVo::getName, toList())));
System.out.println(listMap1);
Map> map = Stream.of(1, 0, 2, -1, 4, -3, 5).collect(groupingBy(o -> {
if (o > 0) {
return "大于";
} else if (o < 0) {
return "小于";
} else {
return "等于";
}
}));
System.out.println(map);
//求和
Map map1 = Stream.of(1, 0, 2, -1, 4, -3, 5).collect(groupingBy(o -> {
if (o > 0) {
return "大于";
} else if (o < 0) {
return "小于";
} else {
return "等于";
}
}, summingInt(Integer::intValue)));
System.out.println(map1);
//partitioningBy和groupingBy类似,但是partitioningBy固定分为两组,key为true和false两个
Map> map2 = Stream.of(1, 0, 2, -1, 4, -3, 5).collect(partitioningBy(integer -> integer > 0));
System.out.println(map2);
}
/**
* 收集数据后再做一些操作
*/
public static void testCollectingAndThen() {
Stream voStream = getStream();
List vos = voStream.collect(collectingAndThen(toList(), studentVos -> studentVos.stream().map(StudentVo::getName).collect(toList())));
System.out.println(vos);
voStream = getStream();
//按照id分组,然后将每个分组的name拼接成字符串
Map stringMap = voStream.collect(groupingBy(StudentVo::getId, collectingAndThen(
mapping(StudentVo::getName, joining(",")), Function.identity())));
System.out.println(stringMap);
}
public static Stream getStream() {
StudentVo vo1 = new StudentVo();
vo1.setId(100001);
vo1.setName("小明");
StudentVo vo2 = new StudentVo();
vo2.setId(100002);
vo2.setName("小红");
StudentVo vo3 = new StudentVo();
vo3.setId(100003);
vo3.setName("小绿");
StudentVo vo4 = new StudentVo();
vo4.setId(100003);
vo4.setName("小黄");
return Stream.of(vo1, vo2, vo3, vo4);
}
}
Function.identity() 等价于 o> o,不做任何变换,返回原对象的函数