Java,  技术

Java Streaming Basic

10年前加入现在的公司的时候公司的产品还在用JDK5,写code自然完全不会用Lamda,Streaming这些8才出现的特性。

后来开始做micro service了,用到新版本的JDK,但是我也很少写code了。中间看了一些书,不过一直是似是而非。是时间仔细看下了。

Intermediate Operations

filter

limit

map

flatMap

Stream.map和Stream.flatMap的区别

先看signature. 区别是 flatMap穿进去一个Item,出来一个Stream:

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

这两个其实是完全不一样的东西,map就是把steam里面的item转换成另外一个,非常简单。flatMap是用来处理item也是list的情况,有时候我们想把两维列表转化成一个,就可以用这。下面是一个简单的例子:

List<List<String>> list = Arrays.asList(
  Arrays.asList("a"),
  Arrays.asList("b"));
System.out.println(list
  .stream()
  .flatMap(Collection::stream)
  .collect(Collectors.toList()));
//https://www.baeldung.com/java-difference-map-and-flatmap

下面是项目的一个更加实际的例子:

Set<ObjectMetadataModel.FieldMapping> fields = metadataStore.getAllObjectsForDataSourceType(object.getDataSourceObject())
                .stream()
                .map(ObjectMetadataModel::getFields)
                .flatMap(Collection::stream)
                .collect(toSet());

这个例子是拿到一个父对象,父对象里面有子对象,这样就能拿到所有的子对象。

总的来说stream就是一个循环,而flatMap就是一个嵌套循环。

下面是另外一个lamda的例子(不是method reference):

//双重循环
for(Suit suit : Suit.values()){
  for(Rank rank : Rank.values()){
     result.add( new Card(suit, rank) );
  }
}

//对应的stream
Stream.of(Suit.values())
  .flatMap( suit -> Stream.of(Rank.values())
                          .map( rank -> new Card(suit.rank)))
  .collect(toList()); // Collectors::toList

Terminal Operation

forEach

forEach其实就是iterate.不用改被用作计算,就是用简单的report,或者简单的操作比如把结果加到另一个colection里面. –<Effective Java>

collect

常用的的下面几种:

toList

toSet

toMap:如果有重复key,会出错。第三个参数可以用来去重。比如可以选择最大,选择最后的一个。

//选择销售额大的
toMap(keyMapper, valueMapper, maxBy(comparing(Album::sales)));
//选择最后的一个
toMap(keyMapper, valueMapper, (v1,v2) -> V2

groupingBy:Value可以是一个数组,也可以是summary,比如`counting()`.

String[] dd = {"absw","resa","eras","dds","basw","rr","rr"};
Arrays.stream(dd).collect(Collectors.groupingBy(e -> e.substring(0,1)))
                .forEach((key, value) -> System.out.println("key:" + key + " value:" + value));
//output
key:a value:[absw]
key:b value:[basw]
key:r value:[resa, rr, rr]
key:d value:[dds]
key:e value:[eras]

Joining: 三个参数,join的delimiter, start character,end character

String chString = str.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(", ", "{", "}"));
//Output:
{Geeks, for, Geeks}

Leave a Reply

Your email address will not be published. Required fields are marked *