当前位置: 首页 > 教程 > Java8 >

Java8 Stream流式编程

精华
小牛编辑
124浏览
2023-03-14

1 Java8 Stream流式编程的介绍

Java在Java 8中提供了一个新的附加程序包,称为java.util.stream。该软件包由类,接口和枚举组成,以允许对元素进行功能样式的操作。您可以通过导入java.util.stream包来使用流。

Stream提供以下功能:

  • 流不存储元素。它只是通过计算操作的流水线从数据结构,数组或I/O通道等源中传递元素。
  • 流本质上是功能性的。对流执行的操作不会修改其源。例如,对从集合中获取的流进行过滤会产生一个新的不带过滤元素的流,而不是从源集合中删除元素。
  • Stream是惰性的,仅在需要时才评估代码。
  • 在流的生存期内,流的元素只能访问一次。像Iterator一样,必须生成新的流以重新访问源中的相同元素。

您可以使用流来过滤,收集,打印以及从一种数据结构转换为另一种数据结构等。在以下示例中,我们借助流来应用了各种操作。

2 Java8 Stream流式编程的方法

方法 描述
boolean allMatch(Predicate<? super T> predicate) 返回此流中与提供的谓词匹配的所有元素。如果流为空,则返回true,并且不评估谓词。
boolean anyMatch(Predicate<? super T> predicate) 返回此流中与提供的谓词匹配的任何元素。如果流为空,则返回false,并且不对谓词求值。
static <T> Stream.Builder<T> builder() 返回一个Stream的生成器。
<R,A> R collect(Collector<? super T,A,R> collector) 使用收集器对此流的元素执行可变还原操作。收集器封装了用作收集参数的函数(供应商,BiConsumer,BiConsumer),从而允许重用收集策略和组成收集操作,例如多级分组或分区。
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) 对该流的元素执行可变的归约运算。可变归约是其中归约值是可变结果容器(例如ArrayList),并且通过更新结果的状态而不是通过替换结果来合并元素。
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) 创建一个延迟串联的流,其元素是第一个流的所有元素,然后是第二个流的所有元素。如果两个输入流都是有序的,则结果流是有序的;如果两个输入流中的任何一个是并行的,则结果流是并行的。关闭结果流后,将同时调用两个输入流的关闭处理程序。
long count() 返回此流中的元素计数。这是减少的特殊情况。
Stream<T> distinct() 返回一个由该流的不同元素组成的流(根据Object.equals(Object))。
static <T> Stream<T> empty() 返回一个空的顺序Stream。
Stream<T> filter(Predicate<? super T> predicate) 返回包含与给定谓词匹配的该流元素的流。
Optional<T> findAny() 返回描述流中某些元素的Optional,如果流为空,则返回空的Optional。
Optional<T> findFirst() 返回描述此流的第一个元素的Optional;如果流为空,则返回一个空的Optional。如果流没有遇到顺序,则可以返回任何元素。
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper) 返回一个流,该流包括将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。将每个映射流的内容放入该流后,将其关闭。(如果映射的流为null,则使用空流。)
DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) 返回一个DoubleStream,该结果包含将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。将每个映射流的内容放入该流后,将其关闭。(如果映射的流为null,则使用空流。)
IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper) 返回一个IntStream,该结果由将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。将每个映射流的内容放入该流后,将其关闭。(如果映射的流为null,则使用空流。)
LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper) 返回一个LongStream,该结果由将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。将每个映射流的内容放入此流后,将其关闭。(如果映射的流为null,则使用空流。)
void forEach(Consumer<? super T> action) 对此流的每个元素执行一个动作。
void forEachOrdered(Consumer<? super T> action) 如果流具有已定义的遇到顺序,则它将按该流的遇到顺序对此流的每个元素执行操作。
static <T> Stream<T> generate(Supplier<T> s) 返回无限顺序无序流,其中每个元素由提供的供应商生成。这适用于生成恒定流,随机元素流等。
static <T> Stream<T> iterate(T seed,UnaryOperator<T> f) 返回通过将函数f迭代应用到初始元素种子而生成的无限顺序有序Stream,该Stream包含种子,f(seed),f(f(seed))等。
Stream<T> limit(long maxSize) 返回由该流的元素组成的流,其长度被截断为不超过maxSize。
<R> Stream<R> map(Function<? super T,? extends R> mapper) 返回一个流,该流包括将给定功能应用于此流的元素的结果。
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) 返回一个DoubleStream,其中包括将给定函数应用于此流的元素的结果。
IntStream mapToInt(ToIntFunction<? super T> mapper) 返回一个IntStream,其中包括将给定函数应用于此流的元素的结果。
LongStream mapToLong(ToLongFunction<? super T> mapper) 返回一个LongStream,其中包括将给定函数应用于此流的元素的结果。
Optional<T> max(Comparator<? super T> comparator) 根据提供的Comparator返回此流的最大元素。这是减少的特殊情况。
Optional<T> min(Comparator<? super T> comparator) 根据提供的Comparator返回此流的最小元素。这是减少的特殊情况。
boolean noneMatch(Predicate<? super T> predicate) 返回此流的元素与提供的谓词匹配。如果流为空,则返回true,并且不评估谓词。
@SafeVarargs static <T> Stream<T> of(T... values) 返回一个顺序有序的流,其元素为指定值。
static <T> Stream<T> of(T t) 返回一个包含单个元素的顺序Stream。
Stream<T> peek(Consumer<? super T> action) 返回由该流的元素组成的流,并在从结果流中消耗元素时对每个元素另外执行提供的操作。
Optional<T> reduce(BinaryOperator<T> accumulator) 使用关联的累加函数对此流的元素进行归约,并返回一个Optional描述归约值(如果有)。
T reduce(T identity, BinaryOperator<T> accumulator) 使用提供的标识值和关联累加函数对此流的元素执行归约,然后返回该归约值。
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) 使用提供的标识,累积和组合功能,它对此流的元素进行简化。
Stream<T> skip(long n) 在丢弃流的前n个元素之后,它将返回由该流的其余元素组成的流。如果此流包含少于n个元素,则将返回空流。
Stream<T> sorted() 返回一个由该流的元素组成的流,并根据自然顺序进行排序。如果此流的元素不可比较,则在执行终端操作时可能会引发java.lang.ClassCastException。
Stream<T> sorted(Comparator<? super T> comparator) 返回一个由该流的元素组成的流,并根据提供的Comparator对其进行排序。
Object[] toArray() 返回一个包含此流元素的数组。
<A> A[] toArray(IntFunction<A[]> generator) 使用提供的生成器函数分配包含此流元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。

3 Java8 Stream流式编程案例:不使用流式编程

在以下示例中,我们在不使用流式编程的情况下过滤数据。

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        List<Float> productPriceList = new ArrayList<Float>();  
        for(Product product: productsList){  
              
            // filtering data of list  
            if(product.price<30000){  
                productPriceList.add(product.price);    // adding price to a productPriceList  
            }  
        }  
        System.out.println(productPriceList);   // displaying data  
    }  
}  

输出结果为:

[25000.0, 28000.0, 28000.0]

4 Java8 Stream流式编程案例:使用流式编程

下面案例中,我们正在使用流式编程来过滤数据。您可以看到代码已经简化了许多:

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
import java.util.stream.Collectors;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        List<Float> productPriceList2 =productsList.stream()  
                                     .filter(p -> p.price > 30000)// filtering data  
                                     .map(p->p.price)        // fetching price  
                                     .collect(Collectors.toList()); // collecting as list  
        System.out.println(productPriceList2);  
    }  
}  

输出结果为:

[90000.0]

5 Java8 Stream流式编程案例:迭代

您可以使用流式编程来迭代任意多次。流式编程提供了预定义的方法来处理您实现的逻辑。在下面的示例中,我们正在迭代,过滤并传递了限制以修复迭代。

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.stream.*;  
public class JavaStreamExample {  
    public static void main(String[] args){  
        Stream.iterate(1, element->element+1)  
        .filter(element->element%5==0)  
        .limit(5)  
        .forEach(System.out::println);  
    }  
}  

输出结果为:

5
10
15
20
25

6 Java8 Stream流式编程案例:过滤和迭代

在下面的示例中,我们使用filter() 方法。在这里,您可以看到代码经过优化并且非常简洁。

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        // This is more compact approach for filtering data  
        productsList.stream()  
                             .filter(product -> product.price == 30000)  
                             .forEach(product -> System.out.println(product.name));    
    }  
}  

输出结果为:

Dell Laptop

7 Java8 Stream流式编程案例:使用collect方法求和

我们还可以使用收集器来计算数值的总和。在下面的示例中,我们使用Collectors类及其指定的方法来计算所有产品价格的总和。

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
import java.util.stream.Collectors;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        // Using Collectors's method to sum the prices.  
        double totalPrice3 = productsList.stream()  
                        .collect(Collectors.summingDouble(product->product.price));  
        System.out.println(totalPrice3);  
          
    }  
} 

输出结果为:

201000.0

8 Java8 Stream流式编程案例:查找最大和最小产品价格

以下示例通过使用流式编程找到最小和最大产品价格。它提供了无需使用命令式方法即可找到值的便捷方法。

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        // max() method to get max Product price   
        Product productA = productsList.stream()  
                        .max((product1, product2)->   
                        product1.price > product2.price ? 1: -1).get();  
          
        System.out.println(productA.price);  
        // min() method to get min Product price  
        Product productB = productsList.stream()  
                .max((product1, product2)->   
                product1.price < product2.price ? 1: -1).get();  
        System.out.println(productB.price);  
          
    }  
}  

输出结果为:

90000.0
25000.0

9 Java8 Stream流式编程案例:Collection的count方法

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
        // count number of products based on the filter  
        long count = productsList.stream()  
                    .filter(product->product.price<30000)  
                    .count();  
        System.out.println(count);  
    }  
}  

输出结果为:

3

10  Java8 Stream流式编程案例:List转为Set 

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
import java.util.stream.Collectors;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
          
        // Converting product List into Set  
        Set<Float> productPriceList =   
            productsList.stream()  
            .filter(product->product.price < 30000)   // filter product on the base of price  
            .map(product->product.price)  
            .collect(Collectors.toSet());   // collect it as Set(remove duplicate elements)  
        System.out.println(productPriceList);  
    }  
}  

输出结果为:

[25000.0, 28000.0]

11  Java8 Stream流式编程案例:List转为Map

/**
 * 小牛知识库: https://www.xnip.cn
 */
import java.util.*;  
import java.util.stream.Collectors;  
class Product{  
    int id;  
    String name;  
    float price;  
    public Product(int id, String name, float price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  
}  
  
public class JavaStreamExample {  
    public static void main(String[] args) {  
        List<Product> productsList = new ArrayList<Product>();  
  
        //Adding Products  
        productsList.add(new Product(1,"HP Laptop",25000f));  
        productsList.add(new Product(2,"Dell Laptop",30000f));  
        productsList.add(new Product(3,"Lenevo Laptop",28000f));  
        productsList.add(new Product(4,"Sony Laptop",28000f));  
        productsList.add(new Product(5,"Apple Laptop",90000f));  
          
        // Converting Product List into a Map  
        Map<Integer,String> productPriceMap =   
            productsList.stream()  
                        .collect(Collectors.toMap(p->p.id, p->p.name));  
              
        System.out.println(productPriceMap);  
    }  
}

输出结果为:

{1=HP Laptop, 2=Dell Laptop, 3=Lenevo Laptop, 4=Sony Laptop, 5=Apple Laptop}