标签:可变 键值对 简单的 map 场景 编程 形参 介绍 练习
前面学习了Lambda表达式,现在来学习一下根据Lambda表达式衍生出的Stream流和方法引用。
一提到流,可能都只会想到IO流。实际上,流不一定是IO流,今天就来学习一下Stream流。首先我们来看一段传统的集合过滤代码:
// 创建一个List集合,存储姓名
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
// 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
List<String> listA = new ArrayList<>();
for (String s : list) {
if(s.startsWith("张")){
listA.add(s);
}
}
// 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
List<String> listB = new ArrayList<>();
for (String s : listA) {
if (s.length() == 3) {
listB.add(s);
}
}
// 遍历listB集合
for (String s : listB) {
System.out.println("s = " + s);
}
在这段代码中,我们先选出了姓张的,再选出了姓名长度为3的,最后使用增强for循环进行了输出。可以看到代码还是很多的。那么我们如果使用Stream流呢?
// 创建一个List集合,存储姓名
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
// 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
// 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
// 遍历listB集合
list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(name -> System.out.println(name));
可以看到,我们的代码被极大简化了。这就是结合了Stream流和Lambda表达式给我们带来的编程便利。
既然这东西这么好,那我们如何获取和使用呢?这里我们学习以下两种获取方法:
直接上例子看看:
public static void main(String[] args) {
// 把集合转换成Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String,String> map = new HashMap<>();
// 获取键,存储到一个Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
// 获取值,存储到一个Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
// 获取键值对(键与值的映射关系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
// 把数组转换为Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
// 可变参数可以传递数组
Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a","bb","cccc"};
Stream<String> stream8 = Stream.of(arr2);
}
可以看到,Stream流的获取还是十分简单的。那么我们可以用Stream流做到什么呢?
首先要了解,Stream流的方法有两种,一种叫延迟方法(即返回的还是Stream接口自身),一种叫终结方法,返回的类型就不再是Stream接口自身了。
forEach(终结方法)
虽然叫forEach,但和增强for循环还是不太一样的。我们来看看怎么使用:
// 获取一个Stream流
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六");
// 使用Stream流中的方法
stream.forEach(name -> System.out.println("name = " + name));
System.out.println("===========");
filter(延迟方法)
这是我们刚才使用的filter方法,我们来再使用一次看看:
// 创建Stream流
Stream<String> stream1 = Stream.of("张三锋", "李四", "王五", "赵六");
// 对Stream流中的元素进行过滤出姓张的
Stream<String> stream2 = stream1.filter(name -> name.startsWith("张"));
// 遍历stream1
stream2.forEach(name -> System.out.println(name));
map(延迟方法)
map方法,可以进行集合进行转换,如下使用:
// map方法
// 获取Stream流
Stream<String> stream3 = Stream.of("1", "2", "3");
// 使用map方法将字符串转换为Ineger类型的整数
Stream<Integer> stream4 = stream3.map(s -> Integer.parseInt(s));
collect(终结方法)
首先我们要有一个对象:
public class Person {
private String name;
private int age;
}
里面的get,set方法和构造方法就省略了。
然后我们使用collect方法:
List<Person> list1 = new ArrayList<>();
list1.add(new Person("王五",15));
list1.add(new Person("赵四",18));
list1.add(new Person("赵六",20));
Map<String, Integer> map = list1.stream().collect(Collectors.toMap(p -> p.getName(), p->p.getAge()));
可以看到,我们使用Stream流可以很方便的将一个List转换成了一个map。同样的,也可以先处理后转换成List,Set等等。具体的使用请在实际使用中练习吧。
上面我们的使用,实际上已经十分简单了,但能不能更简单呢?可以看到有时候我们的Lambda表达式都只用了一句话,比如下面的这个:
.forEach(name -> System.out.println(name));
这里面的name实际上没有任何意义,只是我们定义的一个形参而已。我们想要的就是输出这个形参罢了。那么我们可以写成下面这样:
.forEach(System.out::println);
是不是更加简单了呢?
这里出现了一个新的符号,双冒号。学过C++的可能会知道,这个符号在C++里叫做作用域符,有一种用法和上面也很像,如类::变量。但在java中这个叫做引用运算符,如果在Lambda表达式中要表达的函数方法已经存在,那么就可以使用这个符号来调用他。
事实上,我们自己定义的方法也可以用,比如上面我们提到的collect方法,我们也可以用方法引用这么写:
Map<String, Integer> map = list1.stream().
collect(Collectors.toMap(Person::getName, Person::getAge));
看起来是不是要简单的多了呢。
方法引用的使用方法和场景多种多样,这里只介绍最基本的用法,具体的就请在日后使用到时再了解吧。
这里学习的这些,都是JDK8里的新特性。通过这些新特性的学习,我们可以让代码更加的优雅了。
标签:可变 键值对 简单的 map 场景 编程 形参 介绍 练习
原文地址:https://www.cnblogs.com/wushenjiang/p/13358181.html