流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,你无需写任何多线程代码了。
通过parallelStream或者parallel(内部调用join/fork)就能实现并行操作,需要注意的是线程安全问题及合适的方式采用并行。当然并不是所有并行性能就会好,这里涉及到装箱、拆箱、核数、当前cpu使用率等等。
public class StreamTest extends Java8BaseTest {
@Test
public void test() {
//1 筛选重量大于3 2 映射获取颜色 3 去重 4 排序 5 跳过 6 截流 7 合并
//那么点代码 干了这么多事情,想想,要是不用stream,做这些事情需要多少代码
List<String> colors = apples.stream().filter((Apple a) -> a.getWeight() > 3)
.map(Apple::getColor).distinct().sorted().skip(0).limit(3).collect(toList());
System.out.println(colors.toString());
Assert.assertEquals(colors.size(), 3);
Assert.assertEquals(colors.get(0), "green");
// List转成数组
Apple[] array = apples.toArray(new Apple[0]);
// 输出数组
for (int i = 0; i < array.length; i++) {
System.out.println("array--> " + array[i]);
}
}
@Test
public void matchTest() {
//.allMatch().noneMatch() 匹配 返回true 所以直接结束
Assert.assertEquals(
apples.stream().anyMatch(a -> a.getColor().equals("green")), true);
}
@Test
public void findTest() {
//.findAny() 查找
Assert.assertEquals(apples.stream().findFirst().get().getColor(), "red");
}
@Test
public void reduceTest() {
//reduce 让我们计算下价格总和
Apple c = new Apple(0, 0.0, "");
double allPrice = apples.stream().reduce(c, (Apple a, Apple b) -> {
a.setPrice(a.getPrice() + b.getPrice());
return a;
}).getPrice();
//使用mapToDouble的sum方法也可以实现数值相加,allPrice1这里的值为10.700000000001 精度问题 使用decimal可以解决
double allPrice1 = apples.stream().mapToDouble(Apple::getPrice).sum();
Assert.assertEquals(allPrice == 10.7, true);
}
@Test
public void flatMapTest() {
//flatMap的作用是将多个流合并成一个流
List<List<Apple>> appless = new ArrayList<>();
appless.add(apples);
appless.add(apples);
//获取一个流后还可以使用test1中的操作进行过滤 是否很简洁
List<Apple> newApples = appless.stream().map((List<Apple> a) -> a.toArray(new Apple[a.size()]))
.flatMap(Arrays::stream).collect(toList());
Assert.assertEquals(newApples.size(), apples.size() * 2);
}
@Test
public void pythagoreanTripleTest() {
//在1-100内的勾股数值 比如 3*3+4*4=5*5 这类数据
Stream<int[]> pythagoreanTriples =
//生成1-100的int流 boxed将原始流转换成一般流(不然后面操作返回数据格式就不符合而报错) 即转换为Stream<Integer>
IntStream.rangeClosed(1, 100).boxed()
//因为内置还有个集合,需要使用flatMap方法将其变为一个集合,合并多个集合为一个
.flatMap(a ->
//生成a-100的int流
IntStream.rangeClosed(a, 100)
//过滤勾股数据
.filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
//将Integer转换为数组 这里需要使用mapToObj 否则只能发挥Integer
.mapToObj(b ->
new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
);
pythagoreanTriples
.forEach(t ->
System.out.println(t[0] + ", " + t[1] + ", " + t[2]));
}
@Test
public void groupTest() {
//分组操作
//按颜色对apples进行分组 返回Map<String,List<Apple>> 如果不用流的话,试想下该怎么做
//就一行代码搞定,就问简洁不简洁
// 当然除了groupingBy 还有maxBy(最大 内部其实是通过reducing) minBy(最小) summingInt(求和) summarizingInt(包括求和,平均等等都在里面) joining(连接字符串) reducing 很多方法,自行查看Collectors类
Map<String, List<Apple>> maps = apples.stream().collect(groupingBy(Apple::getColor));
System.out.println(maps.toString());
Assert.assertEquals(maps.size(), 3);
//groupingBy 接收的是Function 即可以返回其他的值,那么就可以在这里做些内容,比如:
//red、yellow 是我最喜欢的,返回 like ,其他为 hate
Map<String, List<Apple>> maps1 = apples.stream().collect(groupingBy((Apple a) -> {
if (a.getColor().equals("red") || a.getColor().equals("yellow")) {
return "like";
} else {
return "hate";
}
}));
System.out.println(maps1.toString());
//groupingBy 还可以接收第二个为Collector的参数代表map中的value值 好吗~ 那么基本上 Collectors方法都可以使用
// 比如 再传一个groupingBy进行二级分组(循环下去就是N级分组) 无非就是Map又包含了Map
// 比如 传一个counting计算个数
Map<String, Long> maps2 = apples.stream().collect(
groupingBy(Apple::getColor, counting()));
System.out.println(maps2.toString());
}
@Test
public void joinTest() {
//查看joining 可知 只能接受字符串 跟我原先想的有些出入 我以为是调用类的.toString()方法获取数据
//下面三种结果都一样,不过 joining 使用的是StringBuilder,所以方法多种多样,joining性能最佳
String str = apples.stream().map(Apple::getColor).collect(joining());
String str1 = apples.stream().map(Apple::getColor)
.collect(reducing((s1, s2) -> s1 + s2)).get();
String str2 = apples.stream()
.collect(reducing("", Apple::getColor, (s1, s2) -> s1 + s2));
Assert.assertEquals(str, str1);
Assert.assertEquals(str, str2);
}
}