jdk 1.8 新特性之——stream Collectors

Collectors的俩个作用:

           1、将数据流缩减为一个单一值,可以是一个collection、基本数据类型或者一个自定义对象;

          2、将数据流中的元素进行分组,根据任务类型将流中所有的任务进行分组。这将产生一个Map<TaskType, List<Task>>的结果,其中每个实体包含一个任务类型以及与它相关的任务。你也可以使用除了列表以外的任何其他的集合。如果你不需要与一任务类型相关的所有的任务,你可以选择产生一个Map<TaskType, Task>。这是一个能够根据任务类型对任务进行分类并获取每类任务中第一个任务的例子。

            3、分割一个流中的元素,将一个流分割为两组。

规约(缩减stream)

     规约成一个列表

List<String> stringList = list.stream().map(Person::getName).collect(toList());

     规约到一个set,toCollection可以指定收集器的实现类型

Set<Person> personSet = list.stream().collect(toSet());
HashSet<Person> personHashSet = list.stream().collect(toCollection(HashSet::new));

     规约到一个map,toMap第一个参数是key,第二个参数为value,第三个参数为key相同时的解决方案,这里取后面的key

Map<Integer, String> 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<Person> list = new ArrayList();
    for (int i = 0; i < 2; i++) {
      list.add(new Person("李雷", i));
      list.add(new Person("小明", i));
    }
    // groupingBy根据指定属性分组
    Map<String, List<Person>> map = list.stream().collect(groupingBy(Person::getName));
    map.forEach((k, v) -> System.out.println(k + "-" + v));
   // 加个参数指定分组后的类型
   Map<String, Set<Person>> map2 = list.stream().collect(groupingBy(Person::getName, toSet()));
   // 聚合操作
   // 分组后value取集合的size
   Map<String, Long> map3 = list.stream().collect(groupingBy(Person::getName, counting()));
   map3.forEach((k, v) -> System.out.println(k + "-" + v));
   // 分组后value取集合的和
   Map<Boolean, Integer> map4 =
      list.stream().collect(partitioningBy(Person::isStudent, summingInt(Person::getType)));
   map4.forEach((k, v) -> System.out.println(k + "-" + v));
   // 分组后,value取分组后最大的person
   Map<String, Optional<Person>> map5 = list.stream()
      .collect(groupingBy(Person::getName, maxBy(Comparator.comparing(Person::getType))));
   map5.forEach((k, v) -> System.out.println(k + "-" + v));
   // 分组,取type Set
   Map<String, Set<Integer>> map6 =
      list.stream().collect(groupingBy(Person::getName, mapping(Person::getType, toSet())));
   map6.forEach((k, v) -> System.out.println(k + "-" + v);

     根据条件分成两组

Map<Boolean, List<Person>> map1 =
        list.stream().collect(partitioningBy(person -> person.getName().equals("小明")));

 

自定义收集器

 

 

public class MultisetCollector<T> implements Collector<T, Multiset<T>, Multiset<T>> {
  @Override
  public Supplier<Multiset<T>> supplier() {
    return HashMultiset::create;
  }

  @Override
  public BiConsumer<Multiset<T>, T> accumulator() {
    return (set, e) -> set.add(e, 1);
  }

  @Override
  public BinaryOperator<Multiset<T>> combiner() {
    return (set1, set2) -> {
      set1.addAll(set2);
      return set1;
    };
  }

  @Override
  public Function<Multiset<T>, Multiset<T>> finisher() {
    return Function.identity();
  }

  @Override
  public Set<Characteristics> characteristics() {
    return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
  }

  public static void main(String[] args) {
    Stream<String> stream = Stream.of("shekhar", "rahul", "shekhar");
    // Multiset可以把重复元素存入的set
    Multiset<String> 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<String, Long> 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<Integer> iStream = Stream.of(1, 3, 2, 4, 6, 5);
    // toList,默认指定收集器为ArrayList
    List<Integer> l = iStream.collect(toList());
    iStream = Stream.of(1, 3, 2, 4, 6, 5);
    Set<Integer> 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<StudentVo> voStream = getStream();
    // toMap,收集为HashMap,第一个参数,key生成,第二个参数,value生成;Function.identity()返回自身
    Map<Long, StudentVo> map = voStream.collect(toMap(StudentVo::getId, Function.identity()));
    System.out.println(map);
    voStream = getStream();
    Map<Long, String> map1 = voStream.collect(toMap(StudentVo::getId, StudentVo::getName));
    // 并发收集
    voStream = getStream();
    Map<Long, String> map2 =
        voStream.collect(toConcurrentMap(StudentVo::getId, StudentVo::getName));
    System.out.println(map2);

    voStream = getStream();
    // key重复,后面覆盖前面的
    Map<Long, String> map4 = voStream
        .collect(toMap(StudentVo::getId, StudentVo::getName, (s, s2) -> s2, LinkedHashMap::new));
    System.out.println(map4);
    voStream = getStream();
    // key重复,取两者间大的那个
    Map<Long, String> 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<Integer> iStream = Stream.of(1, 3, 2, 4, 6, 5);
    // toCollection,可以自定义收集器
    List<Integer> l = iStream.collect(toCollection(LinkedList::new));
    iStream = Stream.of(1, 3, 2, 4, 6, 5);
    Set<Integer> 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<StudentVo> 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<StudentVo> voStream = getStream();
    Map<Long, List<StudentVo>> listMap = voStream.collect(groupingBy(StudentVo::getId));
    System.out.println(listMap);
    voStream = getStream();
    Map<Long, Set<StudentVo>> setMap = voStream.collect(groupingBy(StudentVo::getId, toSet()));
    System.out.println(setMap);
    voStream = getStream();
    //mapping可以自定义要收集的字段
    Map<Long, List<String>> listMap1= voStream.collect(groupingBy(StudentVo::getId, HashMap::new, mapping(StudentVo::getName, toList())));
    System.out.println(listMap1);
    Map<String, List<Integer>> 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<String, Integer> 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<Boolean, List<Integer>> map2 = Stream.of(1, 0, 2, -1, 4, -3, 5).collect(partitioningBy(integer -> integer > 0));
    System.out.println(map2);
  }

  /**
   * 收集数据后再做一些操作
   */
  public static void testCollectingAndThen() {
    Stream<StudentVo> voStream = getStream();
    List<String> vos = voStream.collect(collectingAndThen(toList(), studentVos -> studentVos.stream().map(StudentVo::getName).collect(toList())));
    System.out.println(vos);
    voStream = getStream();
    //按照id分组,然后将每个分组的name拼接成字符串
    Map<Long, String> stringMap = voStream.collect(groupingBy(StudentVo::getId, collectingAndThen(
        mapping(StudentVo::getName, joining(",")), Function.identity())));
    System.out.println(stringMap);
  }

  public static Stream<StudentVo> 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,不做任何变换,返回原对象的函数

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值