Java核心技术·卷二·笔记
第一章:Java8的流库
Java8引入的用来以“做什么而非怎么做”的方式的处理集合
1.1 从迭代到流的操作
package com.package1;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
var contents = new String(Files.readAllBytes(Paths.get("alice.txt")),StandardCharsets.UTF_8);
List<String> words = List.of(contents.split("\\PL+"));
//里面是一个regex正则表达式,表示的是非字母,split的意思是分裂,这个方法会更具后面的regex返回一个String数组
int count = 0;
for(String w:words){
if(w.length() > 12){
count++;
}
}
//使用流
long count2 = words.stream().filter(w -> w.length() > 12).count();
//将串行的stream修改成parallelStream就可以让流库以并行的方式来执行过滤和计数
long count3 = words.parallelStream().filter(w -> w.length() > 12).count();
}
}
流与集合是有显著的差异的:
- 流并不储存元素。
- 流的操作不会修改其数据源
- 流的操作是尽可能的惰性执行的。这意味着可以操作无限流
流遵循了“做什么而非怎么做的原则”,描述了需要做什么,而交给Java本身去实现,给了Java的优化空间,相对于自行指定操作流程,更方便也更快捷
- 创建流
- 转换流
- 应用终止操作,从而产生结果
1.2 流的创建
可以用Collection接口的的stream方法将任何的集合转换成流。也可以使用静态的Stream.of方法
Stream<String> words= Stream.of(contains.split("\\PL+"));
//of具有可变长度,可以构建具有任意数量引元的流
Stream<String> song = Stream.of("gently","down","the","stream");
//使用Array.stream(array,from,to)可以使用数组的一部分元素来创建一个流
//创建一个不包含任何元素的流
Stream<String> silence = Stream.empty();
在操作流的时候,并没有对流背后的集合进行操作.因此对流的引元进行删除等操作是错误而且毫无意义的.
package com.package1;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Test {
public static void main(String[] args) throws IOException {
//下面会展示大部分的创建流的操作
Path path = Paths.get("../gutenberg/alice30.txt");
var contents = new String(Files.readAllBytes(path),StandardCharsets.UTF_8);
Stream<String> words = Stream.of(contents.split("\\PL+"));
//of方法会产生一个元素为给定值的流
//static <T> Stream<T> of(T... values);
show("words",words);
Stream<String> song = Stream.of("gently","down","the","stream");
show("song",song);
Stream<String> silence = Stream.empty();
show("silence",silence);
Stream<String> echos= Stream.generate(()->"Echo");
//generate方法产生一个无限流,它是通过不断调用函数s来构建的
//static <T> Stream<T> generate(Supplier<T> s)
show("echos",echos);
Stream<Double> randoms = Stream.generate(Math::random);
//也可以直接用Java给定的闭包的方法引用
show("randoms",randoms);
Stream<BigInteger> integers = Stream.iterate(BigInteger.ONE,n-> n.add(BigInteger.ONE));
//产生一个无限流,它的原始包括seed,在seed上调用f产生的值,在前一个元素上调用f产生的值
//可以加一个hasNext谓语来指定终止
// static <T> Stream<T> iterate(T seed,UnaryOPerator<T> f)
// static <T> Stream<T> iterate(T seed,Predicate<? super T> hasNext,UnaryOPerator<T> f)
show("integers",integers);
//Java API中大量的方法都可以产生流,例如下面这个方法会将contents里面的字符串分割为一个个单词
Stream<String> wordAnotherWay = Pattern.compile("\\PL+").splitAsStream(contents);
show("wordAnotherWay",wordAnotherWay);
//Files.lines方法会返回一个包含了文件中所有行的Stream
try(Stream<String> lines = Files.lines(path,StandardCharsets.UTF_8)){
show("lines",lines);
}
Iterable<Path> iterable = FileSystems.getDefault().getRootDirectories();
//如果所持有的iterable对象不是集合可以通过下面的调用将其转换成一个流
Stream<Path> rootDirectories = StreamSupport.stream(iterable.spliterator(),false);
show("rootDirections",rootDirectories);
Iterator<Path> iterator = Paths.get("/usr/share/dict/words").iterator();
//如果是Iterator对象,可以使用下面的语句将其转换成流
Stream<Path> pathComponents = StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator, Spliterator.ORDERED),false);
show("pathComponents",pathComponents);
}
public static <T> void show(String title, Stream<T> stream){
final int SIZE= 10;
List<T> firstElements = stream.limit(SIZE+1).collect(Collectors.toList());
System.out.print(title+": ");
for(int i = 0; i < firstElements.size(); i++){
if(i > 0){
System.out.print(", ");
}
if(i < SIZE){
System.out.print(firstElements.get(i));
}
else{
System.out.print("...");
}
}
System.out.println();
}
}
1.3 filter,map和flatMap方法
Stream<T> filter(Predicate<? super T> predicate);
//产生一个流,它包含当前流中所有满足谓语条件的元素
<R> Stream<R> map(Function<? super T,? extends R> mapper);
//产生一个流,它包含将mapper应用于当前流中所有元素所产生的结果
<R> Stream<R> flatmap(Function<? super T, ? extends Stream<? extends R>> mapper);
//产生一个流,它不光实现map的功能,还会将结果连接到一起(注意,这里的每一个结果的都是一个流,即将流连接)
1.4 抽取子流和集合流
Stream<T> limit(long maxSize);
//产生一个流,其中包含了当前流中最初的maxSize个元素
Stream<T> skip(long n);
//舍弃前n个
Stream<T> takeWhile(Predicate<? super T> predicate);
//产生满足条件predicate的流
Stream<T> dropWhile(Predicete<? super T> predicate);
//产生一个流,元素为不满足predicate条件的元素之外的元素
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);
//连接
1.5 其他的流转换
Stream<T> distinct();
//去重
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
//排序,可以加入自己的排序规格
Stream<T> peek(Consumer<? super T> action);
//产生一个流,与原流相同,获取其中每个元素都会将其传递给action;
package com.package1;
import java.util.Comparator;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args){
Stream<String> uniqueWords = Stream.of("Job","Job","Tom","Job").distinct();
uniqueWords.peek(e -> System.out.println(" "+e));
//注意,这是没有任何输出的,因为peek是一个中间操作,而没有终止操作,就只是“流过去”罢了,加一个例如toArray这种终止操作,就会有输出了
Stream<String> longestFirst = words.stream().sorted(Comparator.comparing(String::length).reversed());
Object[] powers = Stream.iterate(1.0,p -> p*2).peek(e -> System.out.println(" "+e)).limit(20).toArray();
}
}
1.6 简单约简
约简是一种终结操作(terminal operation)
它们返回的并非Stream而是Optional类型。Optional类型是一种缺少返回值的更好的方式
以下都是终结操作:
Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);
返回max,min,
Optional<T> findFirst();
Optional<T> findAny();
返回第一个或者任意一个元素,如果流为空,返回空的Optional;
boolean anyMacth(Predicate<? super T> predicate);
boolean allMacth(Predicate<? super T> predicate);
boolean nonMacth(Predicate<? super T> predicate);
任意,所有,没有 元素满足谓语返回true
1.7 Optional 类型
1.7.1 获取Optional的值
可以再没有任何匹配的时候使用默认值
String result = optionalString.orElse("");
也可以从配置文件里面加载默认值
String result = optionalString.orElseGet(() -> System.getProperty("myapp.default"));
也可以抛出异常
String result = optionalString.orElseThrow(IllegalStateException);
1.7.2 消费Optional的值
opionalValue.ifPresent(v->Process v);
例如如果该值存在的情况下将其添加到某个集当中,就可以调用
optionalValue.ifPresent(v -> result.add(v));
//or:
optinalValue.ifPresent(result::add);
也可以实现在满足的时候执行一种动作,在不满足的时候执行另一种动作
optionalValue.ifPresentOrElse(
v->System.out.println("Found"+v),
()->logger.warning("No Match")
);
1.7.3 管道化Optional值
可以使用map来转化Optional内部的值
Optional<String> transformed = optionalString.map(String::toUpperCase);
可以直接用map来进行相关操作
optionalValue.map(result::add);
//还可以添加filter
Optional<String> transformed = optionalString.filter(s -> s.length() >= 8).map(String::toUpperCase);
可以使用or方法将空的Optional替换成一个可替代的Optional。它将以惰性计算
Optional<String> result = optionalString.or(() -> alternatives.stream().findFirst());
1.7.4 不适合使用Optional值的方式
对于Optional的使用,应该遵循以下原则:
- Optional类型的变量永远都不应该为null
- 不要使用Optional类型域,这只会额外多出来一个对象(所谓域,其实是“field”的翻译, 也就是我们常说的字段,或者说是属性)
- 不要在集合中放置Optional对象,而且不要将他作为map的键。应该直接收集其中的值
调用Optional的isPresent等方法反而会将问题处理变得复杂
1.7.5 创建Optional的值
static <T> Optional<T> of(T value);
static <T> Optional<T> ofNullable(T value);
//两个方法都会用value的值产生一个Optional,第一个方法在value为空时会抛出NullPointerException异常,第二个会自动调用empty方法产生一个空的Optional
static <T> Optional<T> empty();
1.7.6 用flatMap创建Optional值的函数
<U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper);
将mapper应用于当前Optional值所产生的结果,或者在当前Optional为空时,返回一个空Optional
1.7.7 将Optional转换为流
stream将Optional方法转化成一个或者两个的Stream对象
package com.package1;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
public class Test {
public static void main(String[] args) throws IOException {
var contents = new String(Files.readAllBytes(Paths.get("src/com/package1/demo.txt")), StandardCharsets.UTF_8);
List<String> wordlist = List.of(contents.split("\\PL+"));
Optional<String> optionalValue = wordlist.stream().filter(s -> s.contains("fred")).findFirst();
System.out.println(optionalValue.orElse("No Word") +" contains fred");
Optional<String> optionalString = Optional.empty();
String result = optionalString.orElse("N/A");
System.out.println("result: "+result);
result = optionalString.orElseGet(() -> Locale.getDefault().getDisplayName());
System.out.println("result: "+result);
try{
result = optionalString.orElseThrow(IllegalStateException::new);
System.out.println("result: "+result);
}
catch (Throwable t){
t.printStackTrace();
}
optionalValue = wordlist.stream().filter(s -> s.contains("red")).findFirst();
optionalValue.ifPresent(s -> System.out.println(s+"contains red"));
var results = new HashSet<String>();
optionalValue.ifPresent(results::add);
Optional<Boolean> added = optionalValue.map(results::add);
System.out.println(added);
System.out.println(inverse(4.0).flatMap(Test::squareRoot));
System.out.println(inverse(-1.0).flatMap(Test::squareRoot));
System.out.println(inverse(0.0).flatMap(Test::squareRoot));
Optional<Double> result2 = Optional.of(-4.0).flatMap(Test::inverse).flatMap(Test::squareRoot);
System.out.println(result2);
}
public static Optional<Double> inverse(Double x){
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x){
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
}
1.8 收集结果
package com.package1;
import com.sun.source.tree.Tree;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) throws IOException {
Iterator<Integer> iter = Stream.iterate(0, n -> n+1).limit(10).iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
Object[] numbers = Stream.iterate(0, n -> n+1).limit(10).toArray();
System.out.println("Object array:" + numbers+Arrays.toString(numbers));
//注意,由于无法在运行的时候创建泛型数组,所以表达式stream.toArray会返回一个Object数组
try{
var number = (Integer) numbers[0];
System.out.println("number:" + number);
System.out.println("The following state will throw an Exception");
var number2 = (Integer[]) numbers;
//Object[]强制类型转换会由于无法识别转换前后是否属于子类或者同一类而报错
}catch (ClassCastException e){
System.err.println(e);
}
Integer[] number3 = Stream.iterate(0, n -> n+1).limit(10).toArray(Integer[]::new);
//传入构造方法就可以指定类型
System.out.println("Integer Array: "+ number3);
Set<String> noVowelSet = noVowels().collect(Collectors.toSet());
show("noVowelSet",noVowelSet);
TreeSet<String> noVowelTreeSet = noVowels().collect(Collectors.toCollection(TreeSet::new));
show("noVowelTreeSet",noVowelTreeSet);
String result = noVowels().limit(10).collect(Collectors.joining());
System.out.println("Joining: "+result);
result = noVowels().limit(10).collect(Collectors.joining(", "));
System.out.println("Joining with commas "+result);
IntSummaryStatistics summary = noVowels().collect(Collectors.summarizingInt(String::length));
double averageWorldLength = summary.getAverage();
double maxWorldLength = summary.getMax();
System.out.println("averageWorldLength: "+averageWorldLength);
System.out.println("maxWorldLength: "+maxWorldLength);
System.out.println("Foreach: ");
noVowels().limit(10).forEach(System.out::println);
}
public static Stream<String> noVowels() throws IOException {
var contains = new String(Files.readAllBytes(
Paths.get("src/com/package1/demo.txt")), StandardCharsets.UTF_8
);
List<String> wordList = List.of(contains.split("\\PL+"));
Stream<String> words = wordList.stream();
return words.map(s -> s.replaceAll("[aeiouAEIOU]", ""));
}
public static <T > void show (String label, Set< T > set){
System.out.print(label+": "+set.getClass().getName());
System.out.println("["+set.stream().limit(10).map(Object::toString).collect(Collectors.joining(", ")));
}
}
1.9 收集到映射表中
package com.package1;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
Map<Integer, String> idToName = people().collect(Collectors.toMap(Person::getId,Person::getName));
System.out.println("idToName:"+idToName);
Map<Integer, Person> idToPerson = people().collect(Collectors.toMap(Person::getId, Function.identity()));
System.out.println("idToPerson: "+idToPerson.getClass().getName()+idToPerson);
idToPerson = people().collect(
Collectors.toMap(Person::getId,Function.identity(),(existingValue, newValue) -> {
throw new IllegalStateException();
}, TreeMap::new)
);
//第三个引元阐述了如果原有的键值和新的键值产生冲突的解决方法(实际上默认的解决就是抛出异常),第四个引元使得本该为Map的本方法生产了TreeMap.
System.out.println("idToPerson: "+idToPerson.getClass().getName()+idToPerson);
Stream<Locale> locals = Stream.of(Locale.getAvailableLocales());
Map<String,String> languageNames = locals.collect(
Collectors.toMap(
Locale::getDisplayLanguage, l -> l.getDisplayLanguage(l),
(existingValue, newValue) -> existingValue,
TreeMap::new
)
);
System.out.println("languageNames: "+ languageNames);
locals = Stream.of(Locale.getAvailableLocales());
Map<String, Set<String>> countryLanguageSets = locals.collect(Collectors.toMap(
Locale::getDisplayCountry, l -> Set.of(l.getDisplayLanguage()), (a,b) ->{
Set<String> union = new HashSet<>(a);
union.addAll(b);
return union;
}
));
System.out.println("countryLanguageSets"+countryLanguageSets);
}
public static class Person {
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String toString() {
return getClass().getName() + "[id=" + id + "name=" + name + "]";
}
}
public static Stream<Person> people() {
return Stream.of(new Person(100, "Peter"), new Person(1002, "Paul"), new Person(1003, "Mary"));
}
}
result:
=================================================================================
D:\Devlop\Environment\JDK-15.0.2\bin\java.exe "-javaagent:C:\Program Files\Devlop\IDE\JetBrains\IntelliJ IDEA 2021.1.2\lib\idea_rt.jar=50157:C:\Program Files\Devlop\IDE\JetBrains\IntelliJ IDEA 2021.1.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\MuRuo\Desktop\Dev\IDEA\JavaRelearn\out\production\JavaRelearn com.package1.Test
idToName:{100=Peter, 1002=Paul, 1003=Mary}
idToPerson: java.util.HashMap{100=com.package1.Test$Person[id=100name=Peter], 1002=com.package1.Test$Person[id=1002name=Paul], 1003=com.package1.Test$Person[id=1003name=Mary]}
idToPerson: java.util.TreeMap{100=com.package1.Test$Person[id=100name=Peter], 1002=com.package1.Test$Person[id=1002name=Paul], 1003=com.package1.Test$Person[id=1003name=Mary]}
languageNames: {=, 上索布语=hornjoserbšćina, 下索布语=dolnoserbšćina, 世界语=esperanto, 东桑海语=Koyraboro senni, 中库尔德语=کوردیی ناوەندی, 中文=中文, 丹麦语=dansk, 乌克兰语=українська, 乌兹别克语=o‘zbek, 乌尔都语=اردو, =========此处略去很多字============马库阿语=Makua, 马恩语=Gaelg, 马拉加斯语=Malagasy, 马拉地语=मराठी, 马拉雅拉姆语=മലയാളം, 马来语=Melayu, 马耳他语=Malti, 马赛语=Maa, 马赞德兰语=مازرونی, 高棉语=ខ្មែរ, 鲁巴加丹加语=Tshiluba}
countryLanguageSets{巴西=[西班牙语, 葡萄牙语], 泰国=[泰语], =[, 旺杜语, 乌兹别克语, 桑布鲁语, 爪哇语, 宿务语, 隆迪语, 索加语, 克罗地亚语, =========此处略去很多字============科威特=[阿拉伯语], 牙买加=[英语], 世界=[阿拉伯语, 依地文, 普鲁士语, 世界语, 沃拉普克语, 国际语, 英语]}
Process finished with exit code 0
1.10 群组和分区
将相同的值群组成组的方法
Map<String,List<Locale>> countryToLocales = locales.collect(Collector.groupingBy(Locale::getCountry));
//称Locale::getCountry为分类函数
当分类函数是断言函数(即返回值为Boolean的函数时,使用partitioningBy方法更高效
Map<Boolean, List<Locale>> englishAndOtherLocales = locales.collect(
Collectors.partitingBy(l -> l.getLanguage().equals("en")));
List<Locale> englishLocales = englishAndOtherLocales.get(true);
1.11 下游收集器
groupingBy方法产生的映射表的每个值都是一个列表,下游收集器用于处理这些列表
package com.package1;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
//静态引入
public class Test {
public static void main(String[] args) throws IOException{
Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
locales = Stream.of(Locale.getAvailableLocales());
Map<String,Set<Locale>> countryToLocaleSet = locales.collect(groupingBy(Locale::getCountry,toSet()));
System.out.println("countryToLocaleSet: "+countryToLocaleSet);
locales = Stream.of(Locale.getAvailableLocales());
Map<String,Long> countryToLocaleCounts = locales.collect(groupingBy(
Locale::getCountry,counting()
));
System.out.println("countryToLocaleCounts: "+countryToLocaleCounts);
Stream<City> cities = readCities("cities.txt");
Map<String,Integer> stateToCityPopulation = cities.collect(groupingBy(
City::getState,summingInt(City::getPopulation)
));
System.out.println("stateToCityPopulation: "+ stateToCityPopulation);
cities = readCities("cities.txt");
Map<String,Optional<String>> stateToLongestCityName = cities.collect(groupingBy(
City::getState,mapping(City::getName,maxBy(Comparator.comparing(String::length
)))
));
locales = Stream.of(Locale.getAvailableLocales());
Map<String,Set<String>> countryToLanguages = locales.collect(groupingBy(
Locale::getDisplayCountry,mapping(Locale::getDisplayLanguage,toSet())
));
cities = readCities("cities.txt");
Map<String,IntSummaryStatistics> stateToCityPopulationSummary = cities.collect(
groupingBy(City::getState,summarizingInt(City::getPopulation))
);
System.out.println(stateToCityPopulationSummary.get("NY"));
cities = readCities("cities.txt");
Map<String,String> stateToCityNames = cities.collect(groupingBy(
City::getState,reducing("",City::getName,(s,t) -> s.length() == 0 ? t : s + "," +t)
));
cities = readCities("cities.txt");
stateToCityNames = cities.collect(groupingBy(City::getState,mapping(City::getName,joining(","))));
}
public static class City{
private String name;
private String state;
private int population;
public City(String name, String state, int population) {
this.name = name;
this.state = state;
this.population = population;
}
public String getName() {
return name;
}
public String getState() {
return state;
}
public int getPopulation() {
return population;
}
}
public static Stream<City> readCities(String filename) throws IOException{
return Files.lines(Paths.get(filename)).map(l -> l.split(", ")).map(a -> new City(a[0],a[1],Integer.parseInt(a[2])));
}
}
1.12 约简操作
对于v1 op v2 , v2 op v3, v3 op v4, …, vn op vn+1…,称op为约简操作,在实际中,例如求和,成绩,字符串连接,求最大值和最小值,求集合的并与交等等(但是需要op操作是可结合的,例如减法操作不满足置换性,就不能使用约简操作)
通常会有一个幺元e使得 e op x = x ,例如在加法操作中幺元是0
如果流为空,则会返回幺元的值,而非Optional类
List<Integer> values = ...;
Optional<Integer> sum = values.stream().reduce((x,y) -> x+y);
//也可以直接写成 reduce(Integer::sum);
List<Integer> values = ...;
Integer sum = values.stream().reduce(0,(x,y) -> x+y);
int result = words.reduce(0,(total,word) -> total + world.length,(total1,total2) -> total1+total2);
//第一个lambda表达式表示将每个单词的个数相加,第二个lambda表达式指出如果多线程操作,将每个线程的结果再相加形成最终结果
1.13 基本类型流
IntStream,LongStream,DoubleStream .... 用来直接存储基本类型值,而无需使用包装器
package com.package1;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) throws IOException{
IntStream is1 = IntStream.generate(() ->(int)(Math.random()*100));
show("is1",is1);
IntStream is2 = IntStream.range(5,10);
show("is2",is2);
IntStream is3 = IntStream.rangeClosed(5,10);
//10 is included
show("is3",is3);
Path path = Paths.get("./src/com/package1/demo.txt");
var contents = new String((Files.readAllBytes(path)), StandardCharsets.UTF_8);
Stream<String> words = Stream.of(contents.split("\\PL+"));
IntStream is4 = words.mapToInt(String::length);
//mapTo...方法按照传入的lambda表达式对每一个元素进行映射操作,转化成基本类型流
show("is4",is4);
var sentences = "\uD835\uDD46 is the set of octonions";
System.out.println(sentences);
IntStream codes =sentences.codePoints();
//CharSequence接口的codePoints方法,生成由字符的UnionCode码或者UTF-16编码机制的码元构成的IntStream
System.out.println(codes.mapToObj(c -> String.format("%X",c)).collect(Collectors.joining()));
Stream<Integer> integers = IntStream.range(0,100).boxed();
//boxed方法将基本类型流转换为对象流
IntStream is5 = integers.mapToInt(Integer::intValue);
show("is5",is5);
}
public static void show(String title, IntStream stream){
final int SIZE = 10;
int[] firstElements = stream.limit(SIZE+1).toArray();
System.out.print(title+": ");
for(int i = 0; i < firstElements.length; i++){
if(i > 0){
System.out.print(", ");
}
if(i < SIZE){
System.out.print(firstElements[i]);
}
else{
System.out.print("...");
}
}
System.out.println();
}
}
1.14 并行流
看不懂,以后再来细啃
本文详细介绍了Java8引入的流库,包括从迭代到流的操作、流的创建、filter、map和flatMap方法的使用,以及流的转换、收集结果、收集到映射表中、约简操作等。内容涵盖了如何处理集合、生成无限流、并行流以及基本类型流,并通过实例展示了如何在实际编程中应用这些概念和方法。
377

被折叠的 条评论
为什么被折叠?



