二嚷缭、流處理
1、流的概念
流:從支持?jǐn)?shù)據(jù)操作的源耍贾,生產(chǎn)而來的元素序列阅爽。
這里源可以是集合,輸入/數(shù)據(jù)流等荐开,有序序列生成的元素序列仍保持之前的順序付翁。
流操作分為中間操作和終端操作,可以順序執(zhí)行也可以并行執(zhí)行晃听。
流操作特點(diǎn):流水線百侧、內(nèi)部迭代(相比之前為外部迭代或顯式迭代)。
注意:終端操作只能進(jìn)行一次能扒,如不能forEach后再次forEach
public static List<String> getLowCaloricDishesNamesInJava8(List<Dish> dishes){
return dishes.stream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());
}
流的性能問題:http://www.importnew.com/17262.html
2佣渴、 常用流操作
(1)篩選切片
Streams接口支持filter方法,該接收接收一個(gè)謂詞(返回boolean的函數(shù))作為參數(shù)初斑,返回一個(gè)符合謂詞的元素的流辛润。如:
// Filtering unique elements
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()//對元素做去重
.forEach(System.out::println);
// Truncating a stream
List<Dish> dishesLimit3 =
menu.stream()
.filter(d -> d.getCalories() > 300)
.limit(3)//返回流的前3個(gè)
.collect(toList());
dishesLimit3.forEach(System.out::println);
// Skipping elements
List<Dish> dishesSkip2 =
menu.stream()
.filter(d -> d.getCalories() > 300)
.skip(2)//返回流的后2個(gè)
.collect(toList());
dishesSkip2.forEach(System.out::println);
(2)映射:map與flatmap
StreamAPI的map方法、flatMap對流中每個(gè)元素應(yīng)用函數(shù)见秤,不同之處在于flatMap將流中每個(gè)元素轉(zhuǎn)化一個(gè)流砂竖,然后把所有流連成一個(gè)流(扁平化)。
// map
List<String> dishNames = menu.stream()
.map(Dish::getName)
.collect(toList());
System.out.println(dishNames);
// map
List<String> words = Arrays.asList("Hello", "World");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(toList());//通過collect將流Stream轉(zhuǎn)成集合
System.out.println(wordLengths);
// flatMap
words.stream()
.flatMap((String line) -> Arrays.stream(line.split("")))
.distinct()
.forEach(System.out::println);
// flatMap
List<Integer> numbers1 = Arrays.asList(1,2,3,4,5);
List<Integer> numbers2 = Arrays.asList(6,7,8);
List<int[]> pairs =
numbers1.stream()
.flatMap((Integer i) -> numbers2.stream()
.map((Integer j) -> new int[]{i, j})
)
.filter(pair -> (pair[0] + pair[1]) % 3 == 0)
.collect(toList());
pairs.forEach(pair -> System.out.println("(" + pair[0] + ", " + pair[1] + ")"));
//輸出(1,8)鹃答、(2,7)乎澄、(3,6)
(3)查找和匹配
StreamAPI提供方法:
allMatch:檢查謂詞是否匹配所有元素
anyMatch:檢查謂詞是否至少匹配一個(gè)元素
noneMatch:相對于allMatch,檢查流中沒有任何元素和謂詞匹配
findAny:返回流中任意元素
findFirst:查找流中第一個(gè)元素
public static void main(String...args){
if(isVegetarianFriendlyMenu()){
System.out.println("Vegetarian friendly");
}
System.out.println(isHealthyMenu());
System.out.println(isHealthyMenu2());
Optional<Dish> dish = findVegetarianDish();
dish.ifPresent(d -> System.out.println(d.getName()));
}
private static boolean isVegetarianFriendlyMenu(){
return menu.stream().anyMatch(Dish::isVegetarian);
}
private static boolean isHealthyMenu(){
return menu.stream().allMatch(d -> d.getCalories() < 1000);
}
private static boolean isHealthyMenu2(){
return menu.stream().noneMatch(d -> d.getCalories() >= 1000);
}
//findAny返回一個(gè)Optional容器實(shí)例测摔,找不到元素避免使用null
//isPresent :Optional有值返回true
//ifPresent:有值時(shí)執(zhí)行其中代碼塊
private static Optional<Dish> findVegetarianDish(){
return menu.stream().filter(Dish::isVegetarian).findAny();
}
(4)規(guī)約
reduce操作將流中所有元素反復(fù)結(jié)合置济。
public static void main(String...args){
List<Integer> numbers = Arrays.asList(3,4,5,1,2);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);//求和
System.out.println(sum);
int sum2 = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum2);
int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
System.out.println(max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);
min.ifPresent(System.out::println);
//沒有初始值,流為空則沒有返回避咆,因此返回使用Optional
int calories = menu.stream()
.map(Dish::getCalories)
.reduce(0, Integer::sum);
System.out.println("Number of calories:" + calories);
}
(5)數(shù)值流:
java8引入三個(gè)原始類型特化流IntStream舟肉、DoubleStream、LongSteam查库,分別將流中元素特化為int路媚、long、double樊销。
boxed()方法則對原始類型進(jìn)行裝箱整慎。
數(shù)值流自帶sum脏款、max、min裤园、average等方法撤师。
int calories = menu.stream()
.mapToInt(Dish::getCalories)
.sum();
System.out.println("Number of calories:" + calories);
// max and OptionalInt
OptionalInt maxCalories = menu.stream()
.mapToInt(Dish::getCalories)
.max();
int max = maxCalories.orElse(1);//沒有最大值,設(shè)置默認(rèn)值1
// numeric ranges
IntStream evenNumbers = IntStream.rangeClosed(1, 100)
.filter(n -> n % 2 == 0);
//rangeClosed包含結(jié)束值拧揽,而range不包含結(jié)束值
System.out.println(evenNumbers.count());
//返回(1,100)符合勾股定理的三元組
Stream<int[]> pythagoreanTriples =
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
.filter(t -> t[2] % 1 == 0)
);
pythagoreanTriples.forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2]));
(6)構(gòu)建流
流可以由值剃盾、數(shù)組、文件創(chuàng)建
// Stream.of
Stream<String> stream = Stream.of("Java 8", "Lambdas", "In", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);
// Stream.empty
Stream<String> emptyStream = Stream.empty();
// Arrays.stream
int[] numbers = {2, 3, 5, 7, 11, 13};
System.out.println(Arrays.stream(numbers).sum());
//文件流回自動(dòng)關(guān)閉
long uniqueWords = Files.lines(Paths.get("lambdasinaction/chap5/data.txt"), Charset.defaultCharset())
.flatMap(line -> Arrays.stream(line.split(" ")))//生成單詞流
.distinct()
.count();//
System.out.println("There are " + uniqueWords + " unique words in data.txt");
可以由于Stream.iterate和Stream.generate函數(shù)生成無限流(沒有固定大小)
// Stream.iterate
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);
// fibonnaci with iterate
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]})
.limit(10)
.forEach(t -> System.out.println("(" + t[0] + ", " + t[1] + ")"));
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]})
.limit(10)
. map(t -> t[0])
.forEach(System.out::println);
// random stream of doubles with Stream.generate
Stream.generate(Math::random)
.limit(10)
.forEach(System.out::println);
// stream of 1s with Stream.generate
IntStream.generate(() -> 1)
.limit(5)
.forEach(System.out::println);
IntStream.generate(new IntSupplier(){
public int getAsInt(){
return 2;
}
}).limit(5)
.forEach(System.out::println);