写这篇文章,主要是记录java8 stream流的用法,博主也是查阅了一些资料,结合源码总结出stream流的主要用法,篇幅比较长,需要耐心看。
目录
filter过滤
map获取属性并return值
mapToInt mapToLong mapToDouble
flatMap
distinct
sorted
of
peek
limit和skip
forEach
toArray
min
anyMatch ,allMatch ,noneMatch 匹配
Reduce
collect
partitioningBy和groupingBy
Collectors.counting,maxBy,averagingInt
Collectors.collectingAndThen
Collectors.toMap
findAny ,findFirst
filter过滤
Stream<T> filter(Predicate<? super T> predicate)
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
demo:
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
personList.stream().filter(person -> person.getAge()>30).forEach(person -> System.out.println(person));
输出:
Person[name='ewwwea1', age=34, sex='男']
map获取属性并return值
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Function function = new Function<Person, Object>() {
@Override
public Object apply(Person person) {
return person.getName();
}
@Override
public <V> Function<V, Object> compose(Function<? super V, ? extends Person> before) {
return null;
}
@Override
public <V> Function<Person, V> andThen(Function<? super Object, ? extends V> after) {
return null;
}
};
List<String> list= (List<String>) personList.stream().map(Person::getName).collect(Collectors.toList());
mapToInt mapToLong mapToDouble
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
这三个可以借助求和,求平均值,最大值最小值等
Integer sum = personList.stream().mapToInt(person -> person.getAge()).sum();
double average = personList.stream().mapToInt(person -> person.getAge()).average().getAsDouble();
System.out.println(sum);
System.out.println(average);
System.out.println(average);
flatMap
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
map和fllatmap区别:
map:map方法返回的是一个object,map将流中的当前元素替换为此返回值;
flatMap:flatMap方法返回的是一个stream,flatMap将流中的当前元素替换为此返回流拆解的流元素;
distinct
返回由不同元素组成的流(根据
{@link Object#equals(Object)}) 这个流。
Stream<T> distinct();
简单去重方法
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
personList =personList.stream().distinct().collect(Collectors.toList());
sorted
排序
返回由该流的元素组成的流,按照自然顺序排序。 如果此流的元素不是 {@code Comparable},则在执行终端操作时可能会抛出 {@code java.lang.ClassCastException}。
Stream<T> sorted();
返回由该流的元素组成的流,根据提供的 {@code Comparator} 进行排序。
Stream<T> sorted(Comparator<? super T> comparator);
/*正序*/
List<User> Asclist = userList.stream().sorted(Comparator.comparingInt(User::getId)).collect(Collectors.toList());
/*倒序*/
List<User> DescList = userList.stream().sorted(Comparator.comparingInt(User::getId).reversed()).collect(Collectors.toList());
of
String[] strings = {"java","python","Math","go","c","c++"};
Stream.of(strings).forEach(System.out::println);
peek
返回一个由该流的元素组成的流,另外在每个元素上执行提供的操作,因为元素从结果流中被消耗。
Stream<T> peek(Consumer<? super T> action);
看下Consumer方法:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
limit和skip
Stream<T> limit(long maxSize);
限制数据量返回由该流的元素组成的流,长度被截断为不超过 maxSize
返回由该流的其余元素组成的流
在丢弃流n个元素之后,如果此流包含少于n个元素,则将返回一个空流。
Stream<T> skip(long n);
forEach
对此流的每个元素执行一个操作,就是遍历元素
void forEach(Consumer<? super T> action);
如果流具有定义的顺序,则按顺序对此流的每个元素执行操作。
void forEachOrdered(Consumer<? super T> action);
toArray
返回一个包含此流元素的数组。
Object[] toArray()
返回一个包含此流元素的数组,使用提供了 {@code generator} 函数来分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
<A> A[] toArray(IntFunction<A[]> generator);
public interface IntFunction<R> {R apply(int value);}
min
Integer[] integers ={22,12,1,2,3,11,221};
Optional optional = Stream.of(integers).min(Comparator.comparing((Integer::shortValue)));
System.out.println(optional.get());
anyMatch ,allMatch ,noneMatch 匹配
/**
* 部分匹配
*/
boolean rs = personList.stream().anyMatch(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getAge() > 10;
}
});
System.out.println(rs);
/**
* 全部匹配
*/
boolean rs1 = personList.stream().allMatch(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getAge() > 30;
}
});
System.out.println(rs1);
/**
* 全部不匹配
*/
boolean rs2 = personList.stream().noneMatch(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getAge() > 30;
}
});
System.out.println(rs2);
Reduce
Reduce 原意:减少,缩小 根据指定的计算模型将Stream中的值计算得到一个最终结果
Optional<T> reduce(BinaryOperator<T> accumulator);
对Stream中的数据通过累加器accumulator迭代计算,最终得到一个Optional对象
Optional optional = personList.stream().map(person -> person.getAge()).reduce((a, b)->{
return a+b;
});
T reduce(T identity, BinaryOperator<T> accumulator);
提供一个跟Stream中数据同类型的初始值identity,通过累加器accumulator迭代计算Stream中的数据,得到一个跟Stream中数据相同类型的最终结果
demo:
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
Integer optional = personList.stream().map(Person::getAge).reduce(10, (a, b) -> {
System.out.printf("a:%d \n", a);
System.out.printf("b:%d \n", b);
a += b;
System.out.printf("a: %d \n", a);
return a;
});
System.out.println("result:" + optional);
输出结果:
a:10
b:21
a: 31
a:31
b:21
a: 52
a:52
b:13
a: 65
a:65
b:34
a: 99
result:99
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
首先看一下BiFunction的三个泛型类型分别是U、 ? super T、U,参考BiFunction函数式接口apply方法定义可以知道,累加器累加器通过类型为U和? super T的两个输入值计算得到一个U类型的结果返回。也就是说这种reduce方法,提供一个不同于Stream中数据类型的初始值,通过累加器规则迭代计算Stream中的数据,最终得到一个同初始值同类型的结果
demo:
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
ArrayList<Integer> newList = new ArrayList<>();
ArrayList<Integer> accResult_ = Stream.of(10, 11, 12)
.reduce(newList,
(acc, item) -> {
acc.add(item);
System.out.println("item: " + item);
System.out.println("acc+ : " + acc);
return acc;
}, (acc, item) -> {
return null;
});
System.out.println("accResult_: " + accResult_);
System.out.println("newList:" + newList);
输出:
item: 10
acc+ : [10]
item: 11
acc+ : [10, 11]
item: 12
acc+ : [10, 11, 12]
accResult_: [10, 11, 12]
newList:[10, 11, 12]
collect
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
我们主要用Collector的方法 ,简单介绍几个Collectors应用方法
- 转换为集合
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
public static <T, C extends Collection<T>>
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
return new CollectorImpl<>(collectionFactory, Collection<T>::add,
(r1, r2) -> { r1.addAll(r2); return r1; },
CH_ID);
}
demo:
List<String> list = Arrays.asList("java", "python","python", "C++","php","java");
list = list.stream().collect(Collectors.toList());
Set<String> strings =list.stream().collect(Collectors.toSet());
//用LinkedList收集
List<String> linkedListResult = list.stream().collect(Collectors.toCollection(LinkedList::new));
linkedListResult.forEach(System.out::println);
System.out.println("--------------");
//用CopyOnWriteArrayList收集
List<String> copyOnWriteArrayListResult = list.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));
copyOnWriteArrayListResult.forEach(System.out::println);
System.out.println("--------------");
//用TreeSet收集
TreeSet<String> treeSetResult = list.stream().collect(Collectors.toCollection(TreeSet::new));
treeSetResult.forEach(System.out::println);
-
Collectors.joining方法
public static Collector<CharSequence, ?, String> joining() {
return new CollectorImpl<CharSequence, StringBuilder, String>(
StringBuilder::new, StringBuilder::append,
(r1, r2) -> { r1.append(r2); return r1; },
StringBuilder::toString, CH_NOID);
}
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
return joining(delimiter, "", "");
}
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
return new CollectorImpl<>(
() -> new StringJoiner(delimiter, prefix, suffix),
StringJoiner::add, StringJoiner::merge,
StringJoiner::toString, CH_NOID);
}
demo:
List<String> list = Arrays.asList("java", "python", "python", "C++", "php", "java");
String result = list.stream().collect(Collectors.joining(",","[ "," ]"));
System.out.println(result);
输出:
[ java,python,python,C++,php,java ]
partitioningBy和groupingBy
// groupingBy 用于分组
Map<String,List<Person>> map = personList.stream().collect(Collectors.groupingBy(Person::getName));
System.out.println(map);
//partitioningBy 用于分隔
Map<Boolean,List<Person>> map1 = personList.stream().collect(Collectors.partitioningBy(p->{return p.getAge()>30;}));
System.out.println(map1);
输出结果:
{duwea1=[Person[name='duwea1', age=13, sex='男']], xiaoming=[Person[name='xiaoming', age=21, sex='男'], Person[name='xiaoming', age=21, sex='男']], ewwwea1=[Person[name='ewwwea1', age=34, sex='男']]}
{false=[Person[name='xiaoming', age=21, sex='男'], Person[name='xiaoming', age=21, sex='男'], Person[name='duwea1', age=13, sex='男']], true=[Person[name='ewwwea1', age=34, sex='男']]}
Collectors.counting,maxBy,averagingInt
/**
* 计数
*/
Long count = list.stream().collect(Collectors.counting());
System.out.println(count);
/**
* 年龄最大的数据
*/
Optional<Person> person = personList.stream().collect(Collectors.maxBy(Comparator.comparing(Person::getAge)));
if (person.isPresent()) {
System.out.println(person.get());
}
/**
* 平均值
*/
double age = personList.stream().collect(Collectors.averagingInt(Person::getAge));
System.out.println("平均年龄:" + age);
Collectors.collectingAndThen
/**
* 根据属性去重
*/
personList = personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new));
Collectors.toMap
tomap方法:
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);
参数讲解:
keyMapper:Key 的映射函数
valueMapper:Value 的映射函数
mergeFunction:当 Key 冲突时,调用的合并方法
mapSupplier:Map 构造器,在需要返回特定的 Map 时使用
demo:
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
Map<String, Integer> map = personList.stream().collect(Collectors.toMap(Person::getName, Person::getAge, (v1,v2)->v1+v2, TreeMap::new));
System.out.println("map合并后:"+map);
Collectors的一些方法介绍:
java 8 Stream流大全,讲解java 8 stream源码内容
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CXzMmaNVTSq5UNNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zNxgDNzEDM0EzNxATM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
findAny ,findFirst
/**
* 查看第一个
*/
Optional optional = personList.stream().findFirst();
if (optional.isPresent()) {
System.out.println(optional.get());
}
/**
* 随机查看
*/
Optional optional1 = personList.stream().findAny();
if (optional1.isPresent()) {
System.out.println(optional1.get());
}