使用Stream API对集合数据进行操作,就类似于使用sql执行数据库查询。
Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是有关计算的。前者主要是面向内存,存储在内存中,后者主要是面向CPU的,通过CPU实现计算。
Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,Stream讲的是计算
default Stream stream()
返回一个数据流default Stream parallelStream()
返回一个并行流public void createStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
Stream<String> stream = list.stream();
Stream<String> parallelStream = list.parallelStream();
}
public static Stream stream(T[] array)
返回一个流public void createStream() {
Stream<String> arrStream = Arrays.stream(new String[]{"北京", "南京"});
}
public static Stream of(T... values)
@Test
public void createStream() {
Stream<String> streamOf = Stream.of("北京", "南京");
}
多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何的处理。而在终止操作时一次性全部处理,称为惰性求值。
1. 筛选与切片:
filter(Predicate p)
接收Lambda,从流中排除某些元素distinct()
筛选,通过流所生成的元素的hasCode()和equals()去除重复元素limit(long maxSize)
截断流,使其元素不超过给定数量skip(long n)
跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补@Test
public void operateStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
list.add("上海");
list.add("西安");
list.add("厦门");
list.add("兰州");
list.add("石河子");
list.add("乌鲁木齐");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
Stream<String> stream = list.stream();
stream.filter(s -> s.length() > 2).forEach(System.out::println);
System.out.println("******************limit***********************");
stream = list.stream();
stream.limit(3).forEach(System.out::println);
System.out.println("******************skip***********************");
stream = list.stream();
stream.skip(6).forEach(System.out::println);
System.out.println("******************distinct***********************");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
stream = list.stream();
stream.distinct().forEach(System.out::println);
}
2. 映射:
map(Function f)
接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素mapToDouble(ToDoubleFunction f)
接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStreammapToInt(ToIntFunction)
接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStreammapToLong(ToLongFunction f)
接受一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStreamflatMap(Function f)
接受一个函数作为参数,该函数将流中的每个值都换成另一个流,然后把所有流连接成一个流@Test
public void mapStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
list.add("上海");
list.add("西安");
list.add("厦门");
list.add("兰州");
list.add("石河子");
list.add("乌鲁木齐");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
Stream<String> stream = list.stream();
stream.map(s -> s + "2019").forEach(System.out::println);
System.out.println("******************不使用flatMap***********************");
stream = list.stream();
Stream<Stream<Character>> streamStream = stream.map(StreamAPI::fromStringToStream);
streamStream.forEach(s -> s.forEach(System.out::println));
System.out.println("******************flatMap***********************");
stream = list.stream();
Stream<Character> characterStream = stream.flatMap(StreamAPI::fromStringToStream);
characterStream.forEach(System.out::println);
}
public static Stream<Character> fromStringToStream(String str) {
List<Character> characterList = new ArrayList<>();
for(Character c : str.toCharArray()) {
characterList.add(c);
}
return characterList.stream();
}
3. 排序:
sorted()
产生一个新流,其中按自然顺序排序sorted(Comparator com)
产生一个新流,其中俺比较器顺序排序@Test
public void sortStream() {
List<String> list = new ArrayList<>();
list.add("10北京");
list.add("9南京");
list.add("8上海");
list.add("7西安");
list.add("6厦门");
list.add("5兰州");
list.add("4石河子");
list.add("3乌鲁木齐");
list.add("2斯洛伐克");
list.add("1阿尔吉尼亚");
Stream<String> stream = list.stream();
stream.sorted().forEach(System.out::println);
System.out.println("******************sorted(Comparator)***********************");
stream = list.stream();
stream.sorted((o1, o2) -> Integer.compare(o1.length(), o2.length())).forEach(System.out::println);
}
终止操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List, Integer, void
流进行了终止操作后,不能再次使用
1. 匹配与查找:
allMatch(Predicate p)
检查是否匹配所有元素anyMatch(Predicate p)
检查是否至少匹配一个元素noneMatch(Predicate p)
检查是否没有匹配所有元素findFirst()
返回第一个元素findAny()
返回当前流中的任何元素count()
返回流中元素的总数max(Comparator c)
返回流中最大值、min(Comparator c)
返回流中最小值forEach(Comparator c)
内部迭代(使用Collection金额口需要用户去做迭代,称为外部迭代。相反,Stream使用内部迭代,他帮你把迭代做了)@Test
public void matchStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
list.add("上海");
list.add("西安");
list.add("厦门");
list.add("兰州");
list.add("石河子");
list.add("乌鲁木齐");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
Stream<String> stream = list.stream();
boolean allMatch = stream.allMatch(s -> s.length() > 3);
System.out.println(allMatch);
System.out.println("******************anyMatch***********************");
stream = list.stream();
boolean anyMatch = stream.anyMatch(s -> s.length() > 3);
System.out.println(anyMatch);
System.out.println("******************noneMatch***********************");
stream = list.stream();
boolean noneMatch = stream.noneMatch(s -> s.length() > 3);
System.out.println(noneMatch);
System.out.println("******************findFirst***********************");
stream = list.stream();
Optional<String> first = stream.findFirst();
System.out.println(first.get());
System.out.println("******************findAny***********************");
stream = list.stream();
Stream<String> parallelStream = list.parallelStream();
Optional<String> any = parallelStream.findAny();
System.out.println(any.get());
System.out.println("******************count***********************");
stream = list.stream();
long count = stream.count();
System.out.println(count);
System.out.println("******************max***********************");
stream = list.stream();
Optional<String> max = stream.max((o1, o2) -> Integer.compare(o1.length(), o2.length()));
System.out.println(max.get());
System.out.println("******************min***********************");
stream = list.stream();
Optional<String> min = stream.min((o1, o2) -> Integer.compare(o1.length(), o2.length()));
System.out.println(min.get());
}
2. 归约
reduce(T iden, BinaryOperator b)
可以将流中元素反复结合起来,得到一个值,返回Treduce(BinaryOperator b)
可以将流中元素反复结合起来,得到一个值,返回Optional@Test
public void reduceStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
list.add("上海");
list.add("西安");
list.add("厦门");
list.add("兰州");
list.add("石河子");
list.add("乌鲁木齐");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
Stream<String> stream = list.stream();
Optional<String> reduce = stream.reduce((s1, s2) -> s1 + s2);
System.out.println(reduce.get());
System.out.println("*****************************************");
stream = list.stream();
String hello = stream.reduce("hello", (s1, s2) -> s1 + s2);
System.out.println(hello);
}
3. 收集:
collect(Collector c)
将流转换成其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。
另外,Collectors实用类提供了很多静态方法,可以方便的创建常见的收集器实例,具体方法与实例:
toList()
把流中元素收集到ListtoSet()
把流中元素收集到SettoCollection()
把流中元素收集到查ungjiande集合counting()
计算流中元素个数summingInt()
对流中元素的整数属性求和averagingInt
计算流中元素Integer属性的平均值summarizingInt()
收集流中Integer属性的统计值。如:平均值@Test
public void collectStream() {
List<String> list = new ArrayList<>();
list.add("北京");
list.add("南京");
list.add("上海");
list.add("西安");
list.add("厦门");
list.add("兰州");
list.add("石河子");
list.add("乌鲁木齐");
list.add("斯洛伐克");
list.add("阿尔吉尼亚");
list.add("阿尔吉尼亚");
Stream<String> stream = list.stream();
List<String> collectList = stream.filter(s -> s.length() > 3).collect(Collectors.toList());
System.out.println("********************toSet*********************");
stream = list.stream();
Set<String> collectSet = stream.filter(s -> s.length() > 3).collect(Collectors.toSet());
System.out.println(collectSet);
System.out.println("********************toCollection*********************");
stream = list.stream();
ArrayList<String> collectCollection = stream.filter(s -> s.length() > 3).collect(Collectors.toCollection(ArrayList::new));
System.out.println(collectCollection);
System.out.println("********************counting*********************");
stream = list.stream();
Long counting = stream.filter(s -> s.length() > 3).collect(Collectors.counting());
System.out.println(counting);
}