1、java8中有两大最为重要的改变,第一就是Lambda表达式,另一个则是Stream API。
2、Stream API真正把函数式编程风格引入到Java中。这是目前为止,java类库中最好的补充,因为Stream API可以极大地提高java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
3、Stream是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤、和映射数据库等操作。使用Stream API对集合进行的操作是在java层面进行的,就类似于使用SQL执行的数据库查询操作,也可以使用Stream进行并行操作。
4、为什么要学习Stream API?
实际开发中,项目中很多数据源都是来源于Mysql、Oracle等关系型数据库,但对于MongDB、Redis等非关系型数据库查询出来的数据就需要在java层面进行处理。
5、Stream和Collection集合的区别:
集合的增删改查操作是在数据结构(内存)层面进行的,数据源会随之发生改变;
Stream操作是在数据(CPU)层面进行的,数据源不会随之发生改变。
6、图解Stream
7、使用Stream的步骤:
(1)产生一个流(Stream),
一个数据源,获取一个流;
(2)中间链式(流水线式)操作,
一个中间的操作链,对数据源的数据进行处理;
(3)产生一个新流,
一个终止操作,执行中间操作链,产生结果。
注意:Stream操作是延迟执行的,他们会等到需要结果时才会执行。
public static void main(String[] args) {
//1.Collection中的方法
Collection<Integer> collection = new ArrayList<>();
Stream<Integer> stream = collection.stream();
Stream<Integer> stream1 = collection.parallelStream();
//2.Arrays中的stream方法(静态方法,可直接调用)
IntStream stream2 = Arrays.stream(new int[]{1, 2, 3});
//3.Stream中的of方法(静态方法,可直接调用)
Stream<String> stream3 = Stream.of("as", "cx1", "323");
//4.Stream中的方法-创作无限流(结果有无限多个)
/** * 4.1 iterate : 这里的例子可理解为,从2开始,每隔2产生一个数据,总共产生无穷多个 * iterate的第二个参数是UnaryOperator,它是一个接口,继承内置函数型接口Function * public interface UnaryOperator<T> extends Function<T, T> * 此处使用Lambda表达式以及方法引用 */
Stream<Integer> stream4 = Stream.iterate(2, x -> x + 2);
stream4.forEach(System.out::println);
/** * 4.2 generate: * public static<T> Stream<T> generate(Supplier<T> s) * 参数是内置供给型接口Supplier * 此处使用Lambda表达式以及方法引用 */
Stream<Double> stream5 = Stream.generate(() -> Math.random());
stream5.forEach(System.out::println);
}
public class FilterTest {
private static List<Student> stuList;
static {
stuList = Arrays.asList(
new Student(1, "zhangsan1", 12, 171.1, 3001D),
new Student(2, "zhangsan1", 14, 172.1, 4001D),
new Student(3, "zhangsan1", 16, 173.1, 5001D),
new Student(4, "zhangsan1", 18, 174.1, 6001D),
new Student(5, "zhangsan1", 20, 175.1, 7001D),
new Student(6, "zhangsan1", 21, 176.1, 8001D),
new Student(7, "zhangsan1", 22, 177.1, 9001D)
);
};
@Test
public void test01(){
//1.创建Stream流
Stream<Student> s1 = stuList.stream();
//2.中间操作,找年龄大于18岁的学生
Stream<Student> studentStream = s1.filter(x -> x.getAge() >= 18);
//3.终止操作
studentStream.forEach(x-> System.out.println(x.getAge()));
}
/** * 注意如果只执行1、2,不执行终止操作,则不会输出任何结果 * 证明Stream操作的“延迟加载”或叫“惰性加载”:只有执行终止操作,中间操作才会被执行 */
@Test
public void test02(){
//1.创建Stream流
Stream<Student> s1 = stuList.stream();
//2.中间操作,找年龄大于18岁的学生
Stream<Student> studentStream = s1.filter(x -> {
System.out.println("正在执行过滤.......");
return x.getAge() >= 18;
}
);
//3.终止操作
//studentStream.forEach(x-> System.out.println(x.getAge()));
}
/** * 链式操作 */
@Test
public void test03(){
stuList.stream()
.filter(x -> x.getAge() >= 18)
.forEach(x-> System.out.println(x.getAge()));
}
}
@Test
public void test04(){
stuList.stream()
.limit(3)
.forEach(System.out::println);
}
@Test
public void test04(){
stuList.stream()
.skip(3)
.forEach(x->System.out.println(x.getName()));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return Objects.equals(getId(), student.getId()) &&
Objects.equals(getName(), student.getName()) &&
Objects.equals(getAge(), student.getAge()) &&
Objects.equals(getHeight(), student.getHeight()) &&
Objects.equals(getSalary(), student.getSalary());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getName(), getAge(), getHeight(), getSalary());
}
static {
stuList = Arrays.asList(
new Student(1, "zhangsan1", 12, 171.1, 3001D),
new Student(1, "zhangsan1", 12, 171.1, 3001D),
new Student(3, "zhangsan3", 16, 173.1, 5001D),
new Student(4, "zhangsan4", 18, 174.1, 6001D),
new Student(5, "zhangsan1", 20, 175.1, 7001D),
new Student(6, "zhangsan6", 21, 176.1, 8001D),
new Student(7, "zhangsan7", 22, 177.1, 9001D)
);
}
@Test
public void test04(){
stuList.stream()
.distinct()
.forEach(System.out::println);
}
map:接收Lambda,将元素转换成其他形式或提取信息。接收一个参数,该参数会被应用到每个元素上,并将其映射成一个新的元素。
可以通俗的理解成数学中的函数,输入x,将x映射成相应的y,并返回覆盖原来的x,从而形成新的元素。
用法大同小异,都不难。
但,需要注意的是,一部分先查找后返回的API,采用的是Optional进行接收。因为查找的结果有可能是空集合。
具体实例:
终止操作中稍微有点难理解的的就是归约。
T reduce(T identity,BinaryOption accumulator)
方法形参:Collector接口
方法实参:应是Collector接口的实例;如何获取:有一个Collector类,里面提供了各种方法,返回给我们Collector接口实例。
(1)将代码放入指定的集合
由于Map集合结构的特殊性,这里需要注意 ,与以上两个不同的是,需要指定存储的key和value.
(2)总数,平均值,总和,最大值,最小值(太过简单,不做过多描述)
(3)分组(简单)
(4)分区:满足条件的在一个分区,不满足条件的在另一个分区(注意:总共只划分出两个分区)
(5)连接:其实就是字符串拼接
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_43842093/article/details/121441599
内容来源于网络,如有侵权,请联系作者删除!