stream
1、Stream是元素的集合,这点让Stream看起来用些类似Iterator;
2、可以支持顺序和并行的对原Stream进行汇聚的操作;
特性:
• 不存储数据
• 不改变源数据
• 延迟执行
使用步骤:
• 创建Stream数据源;
• 数据处理,转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);
• 对Stream进行聚合(Reduce)操作,获取想要的结果;
创建数据源
1、Collection.stream(); 从集合获取流。
2、Collection.parallelStream(); 从集合获取并行流。
3、Arrays.stream(T array) or Stream.of(); 从数组获取流。
4、BufferedReader.lines(); 从输入流中获取流。
5、IntStream.of() ; 从静态方法中获取流。
6、Stream.generate(); 自己生成流
示例
Test
public void createStream() throws FileNotFoundException {
List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"};
// 集合获取 Stream 流
Stream<String> nameListStream = nameList.stream();
// 集合获取并行 Stream 流
Stream<String> nameListStream2 = nameList.parallelStream();
// 数组获取 Stream 流
Stream<String> nameArrStream = Stream.of(nameArr);
// 数组获取 Stream 流
Stream<String> nameArrStream1 = Arrays.stream(nameArr);
// 文件流获取 Stream 流
BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
Stream<String> linesStream = bufferedReader.lines();
// 从静态方法获取流操作
IntStream rangeStream = IntStream.range(1, 10);
rangeStream.limit(10).forEach(num -> System.out.print(num+","));
System.out.println();
IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
intStream.forEach(num -> System.out.print(num+","));
}
stream常用api示例
@Test
void test(){
List<Integer> list = Arrays.asList(1, 2,2,1, 3, 4, 5, 6, 7, 8, 9);
list.stream()
//.filter(p -> p.equals(1))//过滤器 可以做一些数据的筛选 生成一个新的流,其中包含符合某个特定条件的所有元素。
.distinct() //去重
.sorted() //排序
.limit(3) //只取前面n位数据
.skip(1) //舍弃掉前面n位数据
.collect(Collectors.toList())//把数据收集到集合中
.forEach(System.out::print);
String a = list.stream()
.filter(p -> p.equals(2))
.reduce(Integer :: sum) //对数据做进一步运算
.map(String :: valueOf)//对流中的值进行某种形式的转
.get();
//.findAny().get();//找到任何一个所匹配的元素,就返回
//.anyMatch();//判定集合中是否还有匹配的元素
System.out.println(a);
}
Lambda表达式
示例:
Runnable run = () ->{
System.out.println(11);
}
Runnable run = () -> System.out.println(11);
可以理解为方法引用是lambda表达式的另外一种表达形式
主要有三种语法格式:
• 对象 :: 实例方法名
• 类 :: 静态方法名
• 类 :: 实例方法名
被引用的方法的参数和返回值必须和要实现的抽象方法的参数和返回值一致
无参数无返回值 () -> System.out.println(“Hello WOrld”)
有一个参数无返回值 (x) -> System.out.println(x)
有多个参数,有返回值,有多条lambda体语句 (x,y) -> {};
有多个参数,有返回值,只有一条lambda体语句 (x,y) -> xxxx
String::valueOf 等价于lambda表达式 (s) -> String.valueOf(s)
Math::pow 等价于lambda表达式 (x, y) -> Math.pow(x, y);
HashMap
JDK8优化了HashMap的实现, 主要优化点包括:
• 将链表方式修改成链表或者红黑树的形式
• 修改resize的过程,解决JDK7在resize在并发场景下死锁的隐患
• JDK1.7存储使用Entry数组, JDK8使用Node或者TreeNode数组存储
当链表长度大于8是链表的存储结构会被修改成红黑树的形式。
查询效率从O(N)提升到O(logN)。链表长度小于6时,红黑树的方式退化成链表。
JDK7链表插入是从链表头部插入, 在resize的时候会将原来的链表逆序。
JDK8插入从链表尾部插入, 因此在resize的时候仍然保持原来的顺序。