熟悉了java.util.function下的各种函数式接口后,我们就可以学习下Stream流操作,它使用了各种函数式接口,下面我们来熟悉下它的API。
Stream的获取
static <T> Stream<T> | of(T... values) Returns a sequential ordered stream whose elements are the specified values. |
static <T> Stream<T> | of(T t) Returns a sequential |
数组转换
Object[] | toArray() Returns an array containing the elements of this stream. |
<A> A[] | toArray(IntFunction<A[]> generator) Returns an array containing the elements of this stream, using the provided |
排序
Stream<T> | sorted() Returns a stream consisting of the elements of this stream, sorted according to natural order. |
Stream<T> | sorted(Comparator<? super T> comparator) Returns a stream consisting of the elements of this stream, sorted according to the provided |
去重
Stream<T> | distinct() Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream. |
计数
long | count() Returns the count of elements in this stream. |
过滤
Stream<T> | filter(Predicate<? super T> predicate) Returns a stream consisting of the elements of this stream that match the given predicate. |
遍历
void | forEach(Consumer<? super T> action) Performs an action for each element of this stream. |
void | forEachOrdered(Consumer<? super T> action) Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined |
最值
Optional<T> | max(Comparator<? super T> comparator) Returns the maximum element of this stream according to the provided |
Optional<T> | min(Comparator<? super T> comparator) Returns the minimum element of this stream according to the provided |
规约
规约操作又被称作折叠操作,是通过某个连接动作将所有元素汇总成一个汇总结果的过程
Optional<T> | reduce(BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an |
T | reduce(T identity, BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. |
<U> U | reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. |
map
对Stream每个元素都应用mapper函数
<R> Stream<R> | map(Function<? super T,? extends R> mapper) Returns a stream consisting of the results of applying the given function to the elements of this stream. |
DoubleStream | mapToDouble(ToDoubleFunction<? super T> mapper) Returns a |
IntStream | mapToInt(ToIntFunction<? super T> mapper) Returns an |
LongStream | mapToLong(ToLongFunction<? super T> mapper) Returns a |
flatMap
<R> Stream<R> | flatMap(Function<? super T,? extends Stream<? extends R>> mapper) Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
DoubleStream | flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) Returns an |
IntStream | flatMapToInt(Function<? super T,? extends IntStream> mapper) Returns an |
LongStream | flatMapToLong(Function<? super T,? extends LongStream> mapper) Returns an |
collect操作
结合Collector完成更加复杂的操作
<R,A> R | collect(Collector<? super T,A,R> collector) Performs a mutable reduction operation on the elements of this stream using a |
<R> R | collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) Performs a mutable reduction operation on the elements of this stream. |
案例
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
flatMapToInt();
}
private static void toMap() {
List<String> list = new ArrayList<>();
list.add("Mohan");
list.add("Sohan");
list.add("Mahesh");
Map<String, String> collect = list.stream().collect(Collectors.toMap(Function.identity(), s -> s));
System.out.println(collect);
List<Book> bookList = new ArrayList<>();
bookList.add(new Book("Core Java", 200));
bookList.add(new Book("Learning Freemarker", 150));
bookList.add(new Book("Spring MVC", 300));
// 如果key对应多个value ,Collectors.toMap会报错
Map<String, Integer> bookMap = bookList.stream().collect(Collectors.toMap(Book::getName, Book::getPrice));
System.out.println(bookMap);
// 模拟key对应多个值
bookList.add(new Book("Spring MVC", 300));
bookList.add(new Book("Core Java", 200));
// toMap使用Merge Function (v1, v2) -> v1 + "," + v2) 将key对应的多个值以逗号隔开
Map<Integer, String> priceKeyNameValueMap = bookList.stream()
.collect(Collectors.toMap(Book::getPrice, Book::getName, (v1, v2) -> v1 + "," + v2));
System.out.println(priceKeyNameValueMap);
// 使用Map Supplier 指定返回的Map的类型
LinkedHashMap<Integer, String> linkedHashMap = bookList.stream()
.collect(Collectors.toMap(Book::getPrice, Book::getName, (v1, v2) -> v1 + "," + v2, LinkedHashMap::new));
}
private static void mapToLong() {
LongStream longStream = Stream.of("1", "2", "3").mapToLong(Long::valueOf);
long sum = longStream.sum();
System.out.println(sum);
}
private static void mapToInt() {
IntStream intStream = Stream.of("1", "2", "3").mapToInt(Integer::valueOf);
List<Integer> collect = intStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println(collect);
int sum = Stream.of("1", "2", "3").mapToInt(Integer::valueOf).sum();
System.out.println(sum);
}
private static void sorted() {
Map<Integer, String> map = new HashMap<>();
map.put(1, "BBBB");
map.put(2, "AAAA");
map.put(3, "CCCC");
System.out.println("---Sort by Map Value---");
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue))
.forEach(e -> System.out.println("Key: " + e.getKey() + ", Value: " + e.getValue()));
}
private static void reduce() {
int[] array = {3, 5, 10, 15};
IntStream intStream = Arrays.stream(array);
int sum = intStream.reduce(0, (x, y) -> x + y);
System.out.println("Sum:" + sum);
OptionalInt intOptional = Arrays.stream(array).reduce(Integer::sum);
intOptional.ifPresent(System.out::println);
List<Integer> list2 = Arrays.asList(5, 6, 7);
Stream<Integer> integerStream = list2.parallelStream();
Integer reduce = integerStream.reduce(0, Integer::sum, (p, q) -> p * q);
System.out.println(reduce);
}
private static void flatMapToInt(){
int[][] data = {{1,2},{3,4},{5,6}};
IntStream intStream = Arrays.stream(data).flatMapToInt(row -> Arrays.stream(row));
int sum = intStream.sum();
System.out.println(sum);
}
private static void flatMap() {
Integer[][] data = {{1, 2}, {3, 4}, {5, 6}};
Stream<Integer> integerStream = Arrays.stream(data).flatMap(row -> Arrays.stream(row));
integerStream.filter(num -> num % 2 == 1)
.forEach(s -> System.out.print(s + " "));
}
private static void map() {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
list.stream().map(i -> i * i)
.forEach(s -> System.out.print(s + " "));
Integer[][] data = {{1, 2}, {3, 4}, {5, 6}};
Stream<Stream<Integer>> streamStream = Arrays.stream(data).map(row -> Arrays.stream(row));
streamStream.map(inner -> inner.filter(num -> num % 2 == 1))
.forEach(inner -> inner.forEach(s -> System.out.print(s + " ")));
}
private static void distinct() {
List<Book> list = new ArrayList<>();
{
list.add(new Book("Core Java", 200));
list.add(new Book("Core Java", 200));
list.add(new Book("Learning Freemarker", 150));
list.add(new Book("Spring MVC", 300));
list.add(new Book("Spring MVC", 300));
}
long l = list.stream().distinct().count();
System.out.println("No. of distinct books:" + l);
// 自定义对象Book,重写了equal和hashCode方法
System.out.println("-----distinct------");
list.stream().distinct().forEach(b -> System.out.println(b.getName() + "," + b.getPrice()));
// 自定义去重:根据姓名去重
System.out.println("----distinctByByName-----");
list.stream().filter(distinctByKey(book -> book.getName()))
.forEach(System.out::println);
// 自定义去重:根据价格去重
System.out.println("-----distinctByByPrice-----");
list.stream().filter(distinctByKey(book -> book.getPrice()))
.forEach(System.out::println);
}
// distinct是按照equal和hashCode比较元素是否相等,我们也可以自定义比较相等规则
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> map = new HashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
static class Book {
private String name;
private int price;
public Book(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
final Book book = (Book) obj;
if (this == book) {
return true;
} else {
return (this.name.equals(book.name) && this.price == book.price);
}
}
@Override
public int hashCode() {
int hashno = 7;
hashno = 13 * hashno + (name == null ? 0 : name.hashCode());
return hashno;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
private static void concat() {
Stream<String> concatStream = Stream.concat(Stream.of("a", "b", "c"), Stream.of("b", "c", "d"))
.distinct();
concatStream.forEach(System.out::print);
}
private static void findAny() {
List<String> list = Arrays.asList("Mahesh", "Suresh", "Mohit");
String output = list.stream()
.filter(e -> e.startsWith("M"))
.findAny()
.orElse("NA");
System.out.println(output);
List<Integer> numList = Arrays.asList(21, 22, 23, 24);
numList.stream()
.filter(n -> n % 2 == 0)
.findAny()
.ifPresent(e -> System.out.println(e));
}
private static void findFirst() {
Stream.of(50, 60, 70).findFirst()
.ifPresent(s -> System.out.println(s));
List<String> list = Arrays.asList("Vijay", "Suresh", "Vinod");
String output = list.stream()
.filter(e -> e.startsWith("V")) // Vijay, Vinod
.findFirst() //Vijay
.orElse("NA");
System.out.println(output);
List<Integer> numList = Arrays.asList(31, 32, 33, 34);
numList.stream()
.filter(n -> n % 2 == 0) // 32, 34
.findFirst() //32
.ifPresent(e -> System.out.println(e));
}
private static void count_min_max() {
long count = Stream.of(10, 20, 30).count();
System.out.println("Count:" + count);
List<Integer> numList = Arrays.asList(42, 44, 43, 41);
Comparator<Integer> comparator = Comparator.comparing(Integer::intValue);
Optional<Integer> miOptional = numList.stream().min(comparator);
miOptional.ifPresent(e -> System.out.println("Min:" + e));
Optional<Integer> maxOptional = numList.stream().max(Integer::compare);
maxOptional.ifPresent(e -> System.out.println("Max:" + e));
}
private static void iterate() {
// 指定一个初始值, 作为UnaryOperator的入参, 生成一个无限的stream
Stream<Integer> stream = Stream.iterate(1, n -> n * 2).limit(5);
stream.forEach(s -> System.out.print(s + " "));
}
private static void generate() {
List<Integer> collect = Stream.generate(new Random()::nextInt)
.limit(3)
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
private static void peek() {
// peek是中间操作,在调用终止操作后,才会输出
Stream.of(10, 20, 30).peek(e -> System.out.println(e));
Stream.of(10, 20, 30).peek(e -> System.out.println(e))
.collect(Collectors.toList());
Stream.of(10, 11, 12, 13)
.filter(n -> n % 2 == 0)
.peek(e -> System.out.println("Debug filtered value: " + e))
.map(n -> n * 10)
.peek(e -> System.out.println("Debug mapped value: " + e))
.collect(Collectors.toList());
List<String> list = Arrays.asList("AA", "BB", "CC", "BB", "CC", "AA", "AA");
String output = list.stream()
.distinct()
.peek(e -> System.out.println("Debug value: " + e))
.collect(Collectors.joining(","));
System.out.println(output);
List<String> debugList = new ArrayList<>();
List<String> names = Arrays.asList("Mahesh", "Suresh", "Mahendra");
names.stream()
.filter(el -> el.startsWith("M"))
.peek(e -> debugList.add(e))
.collect(Collectors.toList());
System.out.println(debugList);
}
private static void skip_limit() {
List<Integer> list = new ArrayList(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
List<Integer> afterLimit = list.stream().limit(4).collect(Collectors.toList());
List<Integer> afterSkip = list.stream().skip(4).collect(Collectors.toList());
System.out.println("Limit:" + afterLimit);
System.out.println("Skip:" + afterSkip);
}
private static void toArray() {
List<String> list = Arrays.asList("A", "B", "C", "D");
String[] strings = list.stream().toArray(String[]::new);
System.out.println(Arrays.toString(strings));
strings = list.stream().toArray(size -> new String[size]);
System.out.println(Arrays.toString(strings));
int[] ints = IntStream.of(10, 20, 30, 50).toArray();
System.out.println(Arrays.toString(ints));
int[] ints1 = IntStream.range(10, 20).toArray();
System.out.println(Arrays.toString(ints1));
int[] ints2 = Stream.of(1, 3, 4).mapToInt(i -> i * 2).toArray();
System.out.println(Arrays.toString(ints2));
String[] strings1 = Stream.of("Java", "Angular", "Spring").collect(Collectors.toList()).toArray(new String[0]);
System.out.println(Arrays.toString(strings1));
}
private static void forEachAndForEachOrdered() {
Stream.of("A", "B", "C", "D").forEach(System.out::print);
System.out.println();
Stream.of("A", "B", "C", "D").forEachOrdered(System.out::print);
System.out.println();
// 在并行操作下forEach不能保证顺序
Stream.of("A", "B", "C", "D").parallel().forEach(System.out::print);
System.out.println();
// forEachOrdered能保证顺序,不管是顺序流还是并行流
Stream.of("A", "B", "C", "D").parallel().forEachOrdered(System.out::print);
}
}
希望对大家熟悉api有一定的帮助