1.生成斐波那契数列(Stream基本使用)
要求是编写一个能输出斐波拉契数列(Fibonacci)的LongStream
:
因为Java的范型不支持基本类型,所以我们无法用Stream<long>
这样的类型,会发生编译错误。为了保存long,只能使用Stream<Long>
,但这样会产生频繁的装箱、拆箱操作。
为了提高效率,Java标准库提供了IntStream、LongStream和DoubleStream这三种使用基本类型的Stream,它们的使用方法和范型Stream没有大的区别
public class Main {
public static void main(String[] args) throws IOException {
LongStream fib = LongStream.generate(new FibSupplier());
// 打印Fibonacci数列:1,1,2,3,5,8,13,21...
fib.limit(10).forEach(System.out::println);
}
}
class FibSupplier implements LongSupplier {
long first = 0;
long second = 1;
public long getAsLong() {
long p = second;
second += first;
first = p;
return first;
}
}
2. String 转换为LocalDate (map使用)
正常转换:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* String 类型转为 LocalDate类型
*
*/
public class DemoDate {
public static void main(String[] args) {
String date1 = "2021-06-13";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date2 = LocalDate.parse(date1, fmt);
System.out.println(date1);
System.out.println(date2);
}
}
case1:不指明format
String[] strs = new String[]{"2021-01-02", "2021-07-02"};
Stream.of(strs).map(LocalDate::parse).forEach(System.out::println);
case2: 指明format:
匿名函数版本:
String[] strs = new String[]{"2021-01-02", "2021-07-02"};
Stream.of(strs).map(str -> {
return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}).forEach(System.out::println);
优化版本:
String[] strs = new String[]{"2021-01-02", "2021-07-02"};
Stream.of(strs).map(str -> LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"))).forEach(System.out::println);
3.从一组给定的LocalDate中过滤掉工作日,得到休息日(filter 使用)
filter()除了常用于数值外,也可应用于任何Java对象。
例如,从一组给定的LocalDate中过滤掉工作日,以便得到休息日:
public class Main {
public static void main(String[] args) {
Stream.generate(new LocalDateSupplier())
.limit(31) // 调用31次LocalDateSupplier.get方法,得到31个ldt
.filter(ldt -> ldt.getDayOfWeek() == DayOfWeek.SATURDAY || ldt.getDayOfWeek() == DayOfWeek.SUNDAY) // 过滤掉工作日
.forEach(System.out::println);
}
}
class LocalDateSupplier implements Supplier<LocalDate> {
LocalDate start = LocalDate.of(2021, 1, 1);// 起始日期2021.1.1
int n = -1;
public LocalDate get() {
n++;
return start.plusDays(n); // 起始日期+步进增量n
}
}
3. reduce计算
4. 输出为集合或者数组
输出为List、Set:
一组String先过滤掉空字符串,然后把非空字符串保存到List中
public class Main {
public static void main(String[] args) {
Stream<String> stream = Stream.of("Apple", "", null, "Pear", " ", "Orange");
List<String> list = stream.filter(s -> s != null && !s.isBlank()).collect(Collectors.toList());
System.out.println(list);
}
}
把Stream的每个元素收集到List的方法是调用collect()并传入Collectors.toList()
对象,它实际上是一个Collector实例,通过类似reduce()的操作,把每个元素添加到一个收集器中(实际上是ArrayList)。
类似的,collect(Collectors.toSet())
可以把Stream的每个元素收集到Set中。
输出为数组:
把Stream的元素输出为数组和输出为List类似,我们只需要调用toArray()方法,并传入数组的“构造方法”:
List<String> list = List.of("Apple", "Banana", "Orange");
String[] array = list.stream().toArray(String[]::new);
注意到传入的“构造方法”是String[]::new
,它的签名实际上是IntFunction<String[]>
定义的String[] apply(int)
,即传入int参数,获得String[]数组
的返回值。
输出为map:
如果我们要把Stream的元素收集到Map中,就稍微麻烦一点。因为对于每个元素,添加到Map时需要key和value,因此,我们要指定两个映射函数,分别把元素映射为key和value:
public class Main {
public static void main(String[] args) {
Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
Map<String, String> map = stream
.collect(Collectors.toMap(
// 把元素s映射为key:
s -> s.substring(0, s.indexOf(':')),
// 把元素s映射为value:
s -> s.substring(s.indexOf(':') + 1)));
System.out.println(map);
}
}
分组输出
public class Main {
public static void main(String[] args) {
List<String> list = List.of("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots");
Map<String, List<String>> groups = list.stream()
.collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));
System.out.println(groups);
}
}
分组输出使用Collectors.groupingBy()
,它需要提供两个函数:
一个是分组的key,这里使用s -> s.substring(0, 1)
,表示只要首字母相同的String分到一组,
第二个是分组的value,这里直接使用Collectors.toList()
,表示输出为List,上述代码运行结果如下:
{
A=[Apple, Avocado, Apricots],
B=[Banana, Blackberry],
C=[Coconut, Cherry]
}
可见,结果一共有3组,按"A",“B”,"C"分组,每一组都是一个List。
Stream提供的常用操作:
转换操作:map(),filter(),sorted(),distinct();
合并操作:concat(),flatMap();
并行处理:parallel();
聚合操作:reduce(),collect(),count(),max(),min(),sum(),average();
其他操作:allMatch(), anyMatch(), forEach()。