import static java.util.stream.Collectors.toList;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.IntSupplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.Test;
/**
* @author Andypan
* @StraemTest.java
* @{describe}
* @date 2017年8月8日 上午11:08:33
*/
public class StreamTest
{
/**
你可以使用filter、distinct、skip和limit对流做筛选和切片。
你可以使用map和flatMap提取或转换流中的元素。
你可以使用findFirst 和findAny 方法查找流中的元素。你可以用allMatch 、
noneMatch和anyMatch方法让流匹配给定的谓词。
这些方法都利用了短路:找到结果就立即停止计算;没有必要处理整个流。
你可以利用reduce方法将流中所有的元素迭代合并成一个结果,例如求和或查找最大
元素。
filter和map等操作是无状态的,它们并不存储任何状态。reduce等操作要存储状态才
能计算出一个值。sorted和distinct等操作也要存储状态,因为它们需要把流中的所
有元素缓存起来才能返回一个新的流。这种操作称为有状态操作。
流有三种基本的原始类型特化:IntStream、DoubleStream和LongStream。它们的操
作也有相应的特化。
流不仅可以从集合创建,也可从值、数组、文件以及iterate与generate等特定方法
创建。
无限流是没有固定大小的流。
*/
private static List<Transaction> transactions;
static
{
Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
transactions = Arrays.asList(new Transaction(brian, 2011, 300), new Transaction(raoul, 2012, 1000),
new Transaction(raoul, 2011, 400), new Transaction(mario, 2012, 710), new Transaction(mario, 2012, 700),
new Transaction(alan, 2012, 950));
}一个大大的彩蛋:https://mp.csdn.net/postedit/82686446
public static void main(String[] args)
{
// (1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。
transactions.stream().filter(e -> e.getYear() == 2011).sorted(Comparator.comparing(Transaction::getValue))
.collect(toList()).forEach(System.out::println);
// (2) 交易员都在哪些不同的城市工作过?
transactions.stream().map(e -> e.getTrader().getCity()).distinct().collect(toList())
// 或者你可以去掉distinct(),改用toSet()
// transactions.stream().map(e ->
// e.getTrader().getCity()).collect(toS())
.forEach(System.out::println);
// (3) 查找所有来自于剑桥的交易员,并按姓名排序。
transactions.stream().map(e -> e.getTrader()).filter(e -> e.getCity().equals("Cambridge")).distinct()
.sorted(Comparator.comparing(Trader::getName)).collect(toList()).forEach(System.out::println);
// (4) 返回所有交易员的姓名字符串,按字母顺序排序。
transactions.stream().map(Transaction::getTrader).map(Trader::getName).distinct().sorted().collect(toList())
.forEach(System.out::println);
// not efficient!
String names = transactions.stream().map(Transaction::getTrader).map(Trader::getName).distinct().sorted()
.reduce("", (n1, n2) -> n1 + n2);
String names2 = transactions.stream().map(Transaction::getTrader).map(Trader::getName).distinct().sorted()
.collect(Collectors.joining(","));
System.out.println(names2);
// (5) 有没有交易员是在米兰工作
boolean existMilan = transactions.stream().anyMatch(e -> e.getTrader().getCity().equals("Milan"));
System.out.println(existMilan);
// (6) 打印生活在剑桥的交易员的所有交易额。
transactions.stream().filter(e -> e.getTrader().getCity().equals("Cambridge")).map(Transaction::getValue)
.forEach(System.out::println);
// (7) 所有交易中,最高的交易额是多少?
int max = transactions.stream().map(Transaction::getValue).reduce(Integer::max).get();
System.out.println(max);
// (8) 找到交易额最小的交易。
// int min1 =
// transactions.stream().map(Transaction::getValue).reduce(Integer::min).get();
int min2 = transactions.stream().min(Comparator.comparing(Transaction::getValue)).get().getValue();
System.out.println(min2);
}
@Test
public void numberStreamTest()
{
// 映射到数值流(avoid boxing and unboxing)
transactions.stream().mapToInt(Transaction::getValue).sum();
transactions.stream().mapToInt(Transaction::getValue).max().getAsInt();
transactions.stream().mapToInt(Transaction::getValue).average();
IntStream intStream = transactions.stream().mapToInt(Transaction::getValue);
// 转换回对象流
Stream<Integer> stream = intStream.boxed();
IntStream evenNumbers = IntStream.rangeClosed(1, 100).filter(n -> n % 2 == 0);
System.out.println(evenNumbers.count());
// 100以内的勾股数
Stream<int[]> pythagoreanTriples = IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
.mapToObj(b -> new int[] { a, b, (int) Math.sqrt(a * a + b * b) }));
pythagoreanTriples.limit(5).forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2]));
}
@Test
public void buildStreamTest()
{
// (1)由值创建流
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);
// 你可以使用empty得到一个空流
Stream<String> emptyStream = Stream.empty();
// (2)由数组创建流
int[] numbers = { 2, 3, 5, 7, 11, 13 };
int sum = Arrays.stream(numbers).sum();
// (3)由文件生成流
// 用这个方法看看一个文件中有多少各不相同的词
// 你可以使用Files.lines得到一个流,其中的每个元素都是给定文件中的一行。然后,你
// 可以对line调用split方法将行拆分成单词。应该注意的是,你该如何使用flatMap产生一个扁
// 平的单词流,而不是给每一行生成一个单词流。最后,把distinct和count方法链接起来,数
// 数流中有多少各不相同的单词。
long uniqueWords = 0;
try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset()))
{
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count();
} catch (IOException e)
{
}
// (4)由函数生成流:创建无限流
// 1,迭代 iterate
Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
// 斐波那契数列
Stream.iterate(new int[] { 0, 1 }, t -> new int[] { t[1], t[0] + t[1] }).limit(20)
.forEach(t -> System.out.println("(" + t[0] + "," + t[1] + ")"));
// 2,generate
Stream.generate(Math::random).limit(5).forEach(System.out::println);
// 下面的代码就是如何创建一个在调用时返回下一个斐波纳契项的IntSupplier:
IntSupplier fib = new IntSupplier() {
private int previous = 0;
private int current = 1;
public int getAsInt()
{
int oldPrevious = this.previous;
int nextValue = this.previous + this.current;
this.previous = this.current;
this.current = nextValue;
return oldPrevious;
}
};
IntStream.generate(fib).limit(10).forEach(System.out::println);
}
@Test
public void flatMapTest(){
String[] arrayOfWords = { "Goodbye", "World" };
Stream<String> streamOfwords = Arrays.stream(arrayOfWords);
streamOfwords.map(word -> word.split("")) //将每个单词转换为由其字母构成的数组
.flatMap(Arrays::stream)//将各个生成流扁平化为单个流
.distinct()
.collect(toList())
.forEach(System.out::println);
//使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所
//有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。
//一言以蔽之,flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接
//起来成为一个流。
List<Integer> numbers1 = Arrays.asList(1, 2, 3);
List<Integer> numbers2 = Arrays.asList(3, 4);
//List<int[]> pairs =
numbers1.stream()
.flatMap(i -> numbers2.stream().map(j -> new int[]{i, j}))
.collect(toList()).forEach(e -> System.out.println(""+e[0]+" "+e[1]));
System.out.println("----------------");
numbers1.stream()
.flatMap(i -> numbers2.stream().filter(j -> (i+j) % 3 == 0).map(j -> new int[]{i,j})).
forEach(e -> System.out.println(""+e[0]+" "+e[1]));
}
}
class Trader
{
private final String name;
private final String city;
public Trader(String n, String c) {
this.name = n;
this.city = c;
}
public String getName()
{
return this.name;
}
public String getCity()
{
return this.city;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "Trader [name=" + name + ", city=" + city + "]";
}
}
class Transaction
{
private final Trader trader;
private final int year;
private final int value;
public Transaction(Trader trader, int year, int value) {
this.trader = trader;
this.year = year;
this.value = value;
}
public Trader getTrader()
{
return this.trader;
}
public int getYear()
{
return this.year;
}
public int getValue()
{
return this.value;
}
public String toString()
{
return "{" + this.trader + ", " + "year: " + this.year + ", " + "value:" + this.value + "}";
}
}