Stream(流):以一种声明的方式处理数据。
是一个来自数据源的元素队列并支持聚合操作,比如filter, map, reduce, find, match, sorted等。
特点:
1 . 不是数据结构,不会保存数据。
2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)
3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。
IntStream、LongStream 和 DoubleStream 分别表示原始 int 流、 原始 long 流 和 原始 double 流。
这三个原始流类提供了大量的方法用于操作流中的数据,同时提供了相应的静态方法来初始化它们自己。
这三个原始流类都在 java.util.stream 命名空间下。
Stream中的静态方法:of()、iterate()、generate()
iterate()
使用Stream.iterate的最主要作用是抽象迭代逻辑,替代Iterator。Iterator的实现太重,不但需要新建一个class,而且迭代逻辑被分离成了hasNext和next两部分
相对来说,用Stream.iterate来抽象迭代逻辑就方便得多,而且写好之后可以随便扩展,使用filter,map,flatMap,takeWhile,dropWhile等方法得到新的Stream返回给客户代码
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
generate()
Stream<Double> stream3 = Stream.generate(Math::random).limit(2);
stream3.forEach(System.out::println); //0.13511523827758753 0.9366387392872296
reduce
Stream API提供了一些预定义的reduce操作,比如count(), max(), min(), sum()等。
如果我们需要自己写reduce的逻辑,则可以使用reduce方法。
Stream类中有三种reduce,分别接受1个参数,2个参数,和3个参数
1个参数:
List<Integer> num = Arrays.asList(1, 2, 4, 5, 6, 7);
Integer result = num.stream().reduce((x, y) -> {
System.out.println("x:"+x);
return x + y;
}).get();
System.out.println("resutl:"+result);
2个参数:
List<Integer> num = Arrays.asList(1, 2, 3, 4, 5, 6);
Integer result = num.stream().reduce(0,(x, y) -> {
System.out.println("x:" + x);
return x + y;
});
System.out.println("resutl:" + result);
Stream 基础示例
@Test
public void map_map(){
Map<String,String> map1 = new HashMap<>();
map1.put("dan", "good");
map1.put("Jess", "Good");
map1.put("Jaxon", "Bad");
map1.put("Maggie", "Great");
map1.put("Allie", "Bad");
System.out.println("MAP:" + toJsonString(map1.entrySet())); //HashSet集合
//MAP:[{"dan":"good"},{"Jaxon":"Bad"},{"Jess":"Good"},{"Allie":"Bad"},{"Maggie":"Great"}]
Map<String,String> map2 = map1.entrySet().stream().filter(x ->
!x.getKey().equals("dan") && !x.getKey().equals("Allie"))
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
System.out.println(toJsonString(map2)); //{"Jaxon":"Bad","Jess":"Good","Maggie":"Great"}
}
@Test
public void list_map(){
ArrayList<String> alist = new ArrayList<>();
alist.add("a");
alist.add("b");
alist.add("c");
alist.add("a");
System.out.println("1: " + alist);
Map<String, String> collect = alist.stream().collect(
Collectors.toMap(x -> x, x -> {
return x+"!";
},(n1, n2) -> {
System.out.println("只会执行一次" + n1 + ":" + n2);
return n2+"x";
}));
System.out.println(toJsonString(collect)); //{"a":"a!x","b":"b!","c":"c!"}
}
@Test
public void stream_map(){
Map<String, String> collect = Stream.of("a","b","c","d").collect(
Collectors.toMap(x -> x, x -> x+x,(n1, n2) -> n2,TreeMap::new));
System.out.println(toJsonString(collect)); //{"a":"aa","b":"bb","c":"cc","d":"dd"}
}
Stream 示例
public class stream {
String strlist="[{\"颜色\":\"红1\",\"大小\":\"128\",\"price\":\"11\",\"stock_num\":\"22\"},\n" +
"{\"颜色\":\"红2\",\"大小\":\"258\",\"price\":\"33\",\"stock_num\":\"44\"},\n" +
"{\"颜色\":\"黄3\",\"大小\":\"128\",\"price\":\"11\",\"stock_num\":\"66\"},\n" +
"{\"颜色\":\"黄4\",\"大小\":\"258\",\"price\":\"77\",\"stock_num\":\"44\"}]";
@Test
public void test1(){
// Collectors.toList():转换成List集合。/ Collectors.toSet():转换成set集合。
System.out.println(Stream.of("a", "b", "c","a").collect(Collectors.toSet())); //[a, b, c]
System.out.println(Stream.of("a", "b", "c","a").collect(Collectors.toList())); //[a, b, c, a]
// Collectors.toCollection(TreeSet::new):转换成特定的set集合。
TreeSet<String> treeSet = Stream.of("a", "c", "b", "a").collect(Collectors.toCollection(TreeSet::new));
System.out.println(treeSet); //[a, b, c]
//Collectors.joining(","):拼接字符串。 //结果: 1,3,3,2
System.out.println(Stream.of("1", "3", "3", "2").collect(Collectors.joining(",")));
//Collectors.mapping(...):跟Stream的map操作类似,只是参数有点区别
System.out.println(Stream.of(1, 3, 5).collect(Collectors.mapping(x -> x + 1, Collectors.toList())));
//[2, 4, 6]
// Collectors.toMap(keyMapper, valueMapper, mergeFunction):转换成map。
Map<String, String> collect = Stream.of("a", "b", "c", "a").collect(
Collectors.toMap(x -> x, x -> x +"!",(oldVal, newVal) -> newVal));
System.out.println(toJsonString(collect)); //{"a":"a!","b":"b!","c":"c!"}
//可以获取最大值、最小值、平均值、总和值、总数。
//求最小值,相对应的当然也有maxBy方法。
Optional<Integer> int2 = Stream.of(1, 3, 4).collect(Collectors.minBy(Integer::compare));
System.out.println(int2.orElseThrow(null)); //1
Map<Integer, List<Integer>> map = Stream.of(1, 3, 3, 2, 1).collect(Collectors.groupingBy(Function.identity()));
System.out.println(map); //{1=[1, 1], 2=[2], 3=[3, 3]}
//summingInt 求和
Map<Integer, Integer> map1 = Stream.of(1, 3, 3, 2, 1).collect(Collectors.groupingBy(Function.identity(),
Collectors.summingInt(x -> x)
));
System.out.println(map1); //{1=2, 2=2, 3=6}
HashMap<Integer, List<Integer>> hashMap = Stream.of(1, 3, 3, 2, 1).collect(Collectors.groupingBy(Function.identity(),
HashMap::new, Collectors.mapping(x -> x + 1, Collectors.toList())));
System.out.println(hashMap); //{1=[2, 2], 2=[3], 3=[4, 4]}
//Collectors.partitioningBy(x -> x > 2),把数据分成两部分,key为ture/false。第一个方法也是调用第二个方法,
// 第二个参数默认为Collectors.toList()
Map<Boolean, List<Integer>> map2 = Stream.of(1, 3, 3, 2).collect(Collectors.partitioningBy(x -> x > 2));
Map<Boolean, Long> longMap = Stream.of(1, 3, 3, 2).collect(Collectors.partitioningBy(x -> x > 1, Collectors.counting()));
System.out.println(toJsonString(map2)); //{false:[1,2],true:[3,3]}
System.out.println(toJsonString(longMap)); //{false:1,true:3}
}
/**
* 1、Stream中of方法传入可变参数
* 2、Stream中map元素类型转化方法
* 3、Function匿名接口,people匿名对象的使用
* 4、String中split切割方法
* 5、Lambda表达式
* 匿名对象也可以使用Lambda替换,达到精简的效果,因为了便于理解只在forEach遍历下使用了Lambda表达式)。
*/
@Test
public void test3(){
Stream.of("小王:18","小杨:20").map(new Function<String, People>() {
@Override
public People apply(String s) {
String[] str = s.split(":");
People people = new People(str[0],Integer.valueOf(str[1]));
return people;
}
}).forEach(people-> System.out.println( people));
//打印:{name='小王', age=18}
//打印:{name='小杨', age=20}
}
@Test
public void test4(){
// List<Map<String,String>> skuList = toList(strlist, JSONObject.class);
// this.merge(skuList,"stock_num");
List<Map<String,Object>> skuList = toList(strlist, JSONObject.class);
this.order(skuList);
}
//从集合中过滤出来符合条件的元素:
@Test
public void filter(){
List<Map<String,Object>> skuList = toList(strlist, JSONObject.class);
//原本是一个list,stream后也是需要一个返回类型的,所以.collect(Collectors.toList())不能少
List<Map<String,Object>> filterList = skuList.stream().filter(a -> a.get("price").equals("55")).collect(Collectors.toList());
System.err.println("filterList:"+filterList); //filterList:[{"大小":"128","颜色":"黄","price":"55","stock_num":"66"}]
}
/**
* 合并两个具有相同key的map为list
* @param m1 要合并的list
* @param mergeKey 以哪个key为基准合并
* @return
*/
public static List<Map<String, String>> merge(List<Map<String, String>> m1, String mergeKey){
Set<String> set = new HashSet<>();
List<Map<String, String>> reslist=m1.stream()
.filter(map->map.get(mergeKey)!=null)
.collect(Collectors.groupingBy(o->{
set.addAll(o.keySet());//暂存所有key
return o.get(mergeKey).toString(); //按mergeKey分组
}))
.entrySet().stream().map(o->{
Map<String, String> map = o.getValue().stream().flatMap(m->{ //合并
return m.entrySet().stream();
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a,b)->b));
set.stream().forEach(k->{//为没有的key赋值0
if(!map.containsKey(k)) map.put(k, "0");
});
return map;
}).collect(Collectors.toList());
System.out.println(toJsonString(reslist));
//[{"大小":"128","颜色":"黄3","price":"11","stock_num":"66"},{"大小":"258","颜色":"黄4","price":"77","stock_num":"44"},
// {"大小":"128","颜色":"红1","price":"11","stock_num":"22"}]
return reslist;
}
public void order(List<Map<String, Object>> list){
List<Map<String, Object>> list2 = new ArrayList<>();
list2.addAll(list);
List<Map<String, Object>> collect = list.stream().filter(x->{
long count = list2.stream().filter(x2->x2.get("stock_num").equals(x.get("stock_num"))).count();
if(count>1) { //过滤订单数小于2的 ,这种需求很少
return true;
}
return false;
}).collect(Collectors.groupingBy(x->x.get("stock_num"))).entrySet().stream().map(x->{
Map<String, Object> tmp = new HashMap<>();
tmp.put("v", x.getValue());
tmp.put("k", x.getKey());
return tmp; //分组展示重复的订单数据
}).collect(Collectors.toList());
System.out.println("collect: "+toJsonString(collect)); //没有分组C,因为C只有一单 count>1
}
@Test
public void common(){
List<Apple> appleList = new ArrayList<>();//存放apple对象集合
Apple apple1 = new Apple(1,"苹果1",new BigDecimal("3.25"),10);
Apple apple2 = new Apple(1,"苹果2",new BigDecimal("1.35"),20);
Apple apple3 = new Apple(2,"香蕉",new BigDecimal("2.89"),30);
Apple apple4 = new Apple(3,"荔枝",new BigDecimal("9.99"),40);
appleList.add(apple1);
appleList.add(apple2);
appleList.add(apple3);
appleList.add(apple4);
//List 以ID分组 Map<Integer,List<Apple>>
Map<Integer, List<Apple>> groupBy = appleList.stream().collect(Collectors.groupingBy(Apple::getId));
System.out.println("以ID分组:" + toJsonString(groupBy));
//id为key,apple对象为value
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
System.out.println("id为key:" + toJsonString(appleMap));
//从集合中过滤出来符合条件的元素:
List<Apple> filterList = appleList.stream().filter(a -> a.getName().equals("香蕉")).collect(Collectors.toList());
System.out.println("筛选符合条件的数据:" + toJsonString(filterList));
//将集合中的数据按照某个属性求和:
BigDecimal totalMoney = appleList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("求和:" + toJsonString(totalMoney));
// 根据id去重
List<Object> unique = appleList.stream().collect(collectingAndThen(
toCollection(() -> new TreeSet<>(comparingLong(Apple::getId))), ArrayList::new)
);
System.out.println("根据id去重:" + toJsonString(unique));
}
@Test
public void users(){
List<User> userList = Lists.newArrayList(
new User().setId("A").setName("1张三"),
new User().setId("A").setName("2李四"), //new User().setId("B").setName("李四"),
new User().setId("C").setName("3王五"),
new User().setId("D").setName("4赵六"),
new User().setId("A").setName("5杨七")
);
System.out.println("userList:" + toJsonString(userList));
//过去的做法(循环):
Map<String, String> map = new HashMap<>();
for (User user : userList) {
map.put(user.getId(), user.getName());
}
System.out.println("map:" + toJsonString(map)); //{"A":"杨七","C":"王五","D":"赵六"}
// Map<String, String> map2 = userList.stream().collect(Collectors.toMap(User::getId, User::getName));
// System.out.println("map2:" + toJsonString(map2));
//如果存在重复元素,如setId("B")改为setId("A"),如上就会报错,但如下才是正确
/* Map<String, String> map3 = userList.stream().collect(Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1 + n2));
System.out.println("map3:" + toJsonString(map3)); //{"A":"张三李四杨七","C":"王五","D":"赵六"}
Map<String, String> map3 = userList.stream().collect(Collectors.toMap(User::getId, User::getName, (n1, n2) -> {
String str=n1 + n2;
return str;
}));
System.out.println("map3:" + toJsonString(map3)); //{"A":"张三李四杨七","C":"王五","D":"赵六"}*/
//第四参数用于自定义返回 Map 类型,比如希望返回Map是根据Key排序的,可如下:
Map<String, String> map3 = userList.stream().collect(
Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1,TreeMap::new)
);
System.out.println("map3:" + toJsonString(map3)); //{"A":"1张三","C":"3王五","D":"4赵六"}
}
}
@Getter
@Setter
class Apple {
private Integer id;
private String name;
private BigDecimal money;
private Integer num;
public Apple(Integer id, String name, BigDecimal money, Integer num) {
this.id = id;
this.name = name;
this.money = money;
this.num = num;
}
}
@Accessors(chain = true) // 链式方法 new User().setId("A").setName("张三"),
@lombok.Data // User::getId
class User {
private String id;
private String name;
}
@Setter
@Getter
class People {
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "打印:{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
网友评论