流的创建和API的基本使用
在java8中提供了一套流式的数据处理,也就是Stream API,这套API的主要作用就是对数据进行处理,流处理相比于迭代处理的好处如下
Stream API |
迭代遍历 |
相当于一套流水线,对数据一次性处理 |
每次迭代都需要分支进行计算,有时需要多次迭代才能得到最终结果 |
适应现代多核计算机,在几乎不消耗额外资源的情况下进行多线程遍历 |
只能单线程遍历,多线程实现起来过于复杂 |
流的API如下
方法名 |
功能 |
distinct() |
过滤掉集合中的重复元素 |
skip(n) |
跳过前面N个元素 |
limit() |
获得前面N个元素 |
filter(T -> boolean) |
过滤掉表达式返回false的元素 |
anyMatch(T -> boolean) |
查看集合中是否有符合条件的元素,至少返回一个true |
allMatch(T -> boolean) |
查看集合中是否均符合条件,所有都需要返回true |
noneMatch(T -> boolean) |
查看集合中是否均不符合条件,所有都需要返回false |
findFirst() |
返回第一个元素 |
findAny() |
返回任意一个元素,效率相对上一个高 |
reduce(T,(T,T) -> T) |
将集合所有元素聚合成一个 |
partitioningBy(T -> boolean) |
对集合元素进行分区,也就是一个特殊的分组,只能包含两组 |
map(T -> R) |
将每一个元素T映射成元素R,其中每一个元素都是一条流水线 |
flatMap(T -> Stream) |
每一个元素T映射成元素R,所有元素聚合成一个流 |
groupingBy(T -> R) |
根据对集合元素进行分组 |
API的使用
public class ExampleOfCaseMain {
List<Dish> menu;
List<Transcation> transactions;
@Before
public void before() {
menu = Arrays.asList(
new Dish("pork", Boolean.FALSE, 800, Dish.Type.MEAT),
new Dish("beef", Boolean.FALSE, 700, Dish.Type.MEAT),
new Dish("chicken", Boolean.FALSE, 400, Dish.Type.MEAT),
new Dish("french fries", Boolean.TRUE, 530, Dish.Type.OTHER),
new Dish("rice", Boolean.TRUE, 350, Dish.Type.OTHER),
new Dish("season fruit", Boolean.TRUE, 120, Dish.Type.OTHER),
new Dish("pizza", Boolean.TRUE, 550, Dish.Type.OTHER),
new Dish("prawns", Boolean.FALSE, 300, Dish.Type.FISH),
new Dish("salmon", Boolean.FALSE, 450, Dish.Type.FISH)
);
}
@Test
public void test0() {
List<Dish> collect = menu.stream()
.filter(d -> d.getCalories() > 300)
.distinct()
.skip(1)
.limit(2)
.collect(toList());
System.out.println(collect);
}
@Test
public void test1(){
System.out.println(menu.stream().anyMatch(d -> "pork".equals(d.getName())));
System.out.println(menu.stream().allMatch(d -> "pork".equals(d.getName())));
System.out.println(menu.stream().noneMatch(d -> "pork".equals(d.getName())));
System.out.println(menu.stream().findAny());
System.out.println(menu.stream().findFirst());
System.out.println(menu.stream().map(Dish::getName).reduce((a,b)->a+b));
}
@Test
public void test2() {
Map<Integer, Long> collect = menu.stream()
.map(Dish::getName)
.collect(groupingBy(a -> a.length(), counting()));
System.out.println(collect);
Map<Boolean, Map<String, Map<Dish.Type, List<Dish>>>> collect1 = menu.stream()
.collect(
groupingBy(Dish::isVegetarian,
groupingBy(Dish::getName,
groupingBy(Dish::getType))));
System.out.println(collect1);
}
实际需求中的应用
public class ExampleOfCaseMain {
List<Transcation> transactions;
@Before
public void before() {
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 Transcation(brian, 2011, 300),
new Transcation(raoul, 2012, 1000),
new Transcation(raoul, 2011, 400),
new Transcation(mario, 2012, 710),
new Transcation(mario, 2012, 700),
new Transcation(alan, 2012, 950)
);
}
@Test
public void test1() {
List<Transcation> collect = transactions.stream()
.filter(t -> 2011 == t.getYear())
.sorted(comparing(a -> a.getValue()))
.collect(toList());
System.out.println(collect);
}
@Test
public void test2() {
List<String> collect = transactions.stream()
.map(t -> t.getTrader().getCity())
.distinct()
.collect(toList());
System.out.println(collect);
}
@Test
public void test3() {
List<Trader> collect = transactions.stream()
.map(Transcation::getTrader)
.distinct()
.filter(trader -> "Cambridge".equals(trader.getCity()))
.sorted(comparing(Trader::getName))
.collect(toList());
System.out.println(collect);
}
@Test
public void test4() {
List<String> collect = transactions.stream()
.map(t -> t.getTrader().getName())
.distinct()
.sorted()
.collect(toList());
System.out.println(collect);
}
@Test
public void test5() {
boolean milan = transactions.stream()
.map(t -> t.getTrader().getCity())
.anyMatch(c -> "Milan".equals(c));
System.out.println(milan);
}
@Test
public void test6() {
Optional<Integer> cambridge = transactions.stream()
.filter(t -> "Cambridge".equals(t.getTrader().getCity()))
.map(t -> t.getValue())
.reduce(Integer::sum);
System.out.println(cambridge.get());
double sum = transactions.stream()
.filter(t -> "Cambridge".equals(t.getTrader().getCity()))
.mapToDouble(t -> t.getValue())
.sum();
System.out.println(sum);
}
@Test
public void test7() {
Optional<Integer> cambridge = transactions.stream()
.filter(t -> "Cambridge".equals(t.getTrader().getCity()))
.map(t -> t.getValue())
.reduce(Integer::max);
System.out.println(cambridge.get());
}
@Test
public void test8() {
Optional<Transcation> reduce = transactions.stream()
.filter(t -> "Cambridge".equals(t.getTrader().getCity()))
.reduce((a, b) -> a.getValue() < b.getValue() ? a : b);
System.out.println(reduce.get());
}
}