/*
Lambda表达式虽然是匿名内部类的简化写法,但是Lambda表达式有些使用也有些冗余。
s -> System.out.println(s)
Lambda表达式做的事情和println方法做的事情重叠了
这个Lambda表达式做的事情是拿到参数之后,【直接】对参数进行了输出。
如果Lambda表达式拿到参数之后, 【直接】对参数进行处理, 那么其实此时就可以想办法省略参数。
同样的功能,可以使用方法引用去完成,方法引用就可以省略这个参数。
方法引用是Lambda表达式的孪生兄弟, 方法引用是Lambda表达式的简化写法。
方法引用符号是::,可以使用::去实现。
*/
public class Demo01Lambda {
/*
定义方法,使用Consumer当做方法参数。
在方法中使用Consumer输出一个字符串
*/
public static void method(Consumer<String> c) {
//要对字符串进行操作。
c.accept("hello");
}
public static void main(String[] args) {
//调用method方法,传递Lambda表达式,lambda表达式将字符串直接输出
method(s -> System.out.println(s));
//方法引用初体验
method(System.out::println);
}
}
02. 对象引用成员方法
/*
方法引用的常见的四种方式:
1. 对象引用成员方法
2. 类名引用静态方法
3. 类的构造器引用
4. 数组的构造器引用
对象引用成员方法格式:
对象名::方法名
*/
public class Demo01ObjectRef {
/*
定义方法, 使用函数式接口Consumer当做方法参数。
在方法中对字符串进行操作(将字符串转成大写并输出)
*/
public static void method(Consumer<String> c) {
//调用accept方法,操作字符串
c.accept("hello");
}
public static void main(String[] args) {
//调用method方法
//method(s -> System.out.println(s.toUpperCase()));
MyClass myClass = new MyClass();
//method(s -> myClass.printUpperCase(s));
method(myClass::printUpperCase);//表示拿到参数后,直接使用myClass对象的printUpperCase处理这个参数
}
}
public class MyClass {
/*
定义方法, 将一个字符串转成大写并输出
*/
public void printUpperCase(String str) {
System.out.println(str.toUpperCase());
}
}
03. 类名引用静态方法
/*
类名引用静态方法
格式:
类名::静态方法
*/
public class Demo01ClassRef {
/*
定义一个方法,使用函数式接口Function当做方法参数。
在方法使用Function操作数字(求出这个数字的绝对值)
*/
public static void method(Function<Integer, Integer> f) {
//通过Function的apply方法操作数字
int num = f.apply(-10);
System.out.println(num);
}
public static void main(String[] args) {
//调用method方法
method(num -> num > 0 ? num : -num);
//method(num -> num > 0 ? num : -num);
//使用Math的静态方法abs求出绝对值
//method(num -> Math.abs(num));
method(Math::abs); //拿到参数后直接使用Math的静态方法abs处理这个参数
}
}
04. 类的构造器引用
/*
类的构造器引用
类的构造器引用要在创建对象的时候使用。
格式:
类名::new
*/
public class Demo01ClassNew {
/*
定义方法, 使用自己定义的函数式接口PersonBuilder当做参数。
在方法中使用PersonBuilder获取一个Person对象
*/
public static void method(PersonBuilder pd) {
//得到了Person对象。
Person person = pd.createPerson("葫芦娃", 10);
//输出Person
System.out.println(person);
}
public static void main(String[] args) {
//调用method方法,传递Lambda表达式
//method((name, age) -> new Person(name, age));
method(Person::new); //表示拿到参数后,直接根据这些参数使用构造方法创建对象。
}
}
public interface PersonBuilder {
//定义方法,参数传递姓名和年龄, 返回的结果是一个Person。
Person createPerson(String name, int age);
}
public class Person {
private String name;
private int age;
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
05. 数组的构造器引用
/*
数组的构造器引用
数组的构造器引用在创建数组的时候使用。
格式:
数据类型[]::new
*/
public class Demo01ArrayNew {
/*
定义方法,使用函数式接口ArrayBuilder当做方法参数
在方法中使用ArrayBuilder获取一个数组
*/
public static void method(ArrayBuilder arrayBuilder) {
//调用createArray得到一个数组
int[] arr = arrayBuilder.createBuilder(10);
//输出数组
System.out.println(Arrays.toString(arr));
}
public static void main(String[] args) {
//调用method方法,传递一个lambda表达式
//method(len -> new int[len]);
method(int[]::new);//表示拿到参数之后,直接根据这个参数构建一个int数组
}
}
public interface ArrayBuilder {
//定义方法,参数是一个数字表示数组的长度, 返回的结果是一个int数组
int[] createBuilder(int len);
}
06. 传统for循环遍历集合的弊端以及Stream流初体验
/*
定义集合,并添加元素,然后执行下面的操作
1. 首先筛选所有姓张的人;
2. 然后筛选名字有三个字的人;
3. 最后进行对结果进行打印输出。
*/
public class Demo01PrintList {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1. 首先筛选所有姓张的人;
List<String> zhangList = new ArrayList<>();
//遍历原来的集合,拿到里面的每一个元素,判断是否以张开头,如果是就表示姓张,那么就添加到 zhangList
for (String s : list) {
if(s.startsWith("张")) {
zhangList.add(s);
}
}
//2. 然后筛选名字有三个字的人;
List<String> threeList = new ArrayList<>();
//遍历之前筛选后的集合,拿到里面的每一个元素,判断是否是三个字,如果是,就添加到threeList
for (String s : zhangList) {
if(s.length() == 3) {
threeList.add(s);
}
}
//3. 最后进行对结果进行逐一打印输出。
for (String s : threeList) {
System.out.println(s);
}
System.out.println("======================");
//Stream流初体验
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() ==3).forEach(System.out::println);
}
}
07. Stream流的介绍
参考 Java基础学习16:【方法引用、Stream流】的图文章源自JAVA秀-https://www.javaxiu.com/736.html
08. Collection集合获取流
/*
Stream表示流。
获取流的三种方式
1. 通过Collection(单列)集合获取流
2. 通过Map(双列)集合获取流
3. 通过数组获取流
通过Collection(单列)集合获取流的方式
如果要使用Collection单列集合获取流,可以使用Collection中的方法stream去完成。
获取流的方法:
Stream<E> stream(): 获取一个流对象
*/
public class Demo01Stream {
public static void main(String[] args) {
//创建List集合
List<String> list = new ArrayList<>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//获取这个集合对应的流
Stream<String> stream = list.stream();
//将stream流转成数组,借助数组的工具类打印。
System.out.println(Arrays.toString(stream.toArray()));
}
}
09. 通过Map集合获取流
/*
通过Map集合获取流(了解),Map集合不能直接获取流对象, 只能间接获取, 有三种间接获取方式。
1. 先获取Map集合中的所有的key, 然后获取所有key的stream流
2. 先获取Map集合中的所有的value,然后获取所有value的stream流
3. 先获取Map集合中的所有的Entry(键值对), 获取所有entry的stream流。
*/
public class Demo02Stream {
public static void main(String[] args) {
//定义Map集合
Map<String, String> map = new HashMap<>();
//添加元素
map.put("it001", "jack");
map.put("it002", "rose");
map.put("it003", "tony");
//先获取Map集合中的所有的key, 然后获取所有key的stream流
Set<String> keys = map.keySet();
Stream<String> keyStream = keys.stream();
System.out.println(Arrays.toString(keyStream.toArray()));
//先获取Map集合中的所有的value,然后获取所有value的stream流
Collection<String> values = map.values();
Stream<String> valueStream = values.stream();
System.out.println(Arrays.toString(valueStream.toArray()));
//先获取Map集合中的所有的Entry(键值对), 获取所有entry的stream流。
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> entryStream = entries.stream();
System.out.println(Arrays.toString(entryStream.toArray()));
}
}
10. 通过数组获取Stream流
/*
通过数组获取流
方式一:使用Stream的静态方法of完成(推荐, 因为参数不仅可以传递数组, 也可以传递任意个数据)
static <T> Stream<T> of(T... values): 根据一个数组获取一个stream流
方式二: 使用Arrays的静态方法stream完成
static <T> Stream<T> stream(T[] array) : 根据一个数组获取对应的stream流
*/
public class Demo03Stream {
public static void main(String[] args) {
//定义数组
String[] strArr = {"aa", "bb", "cc"};
//方式一:使用Stream的静态方法of完成
//Stream<String> stream = Stream.of(strArr);
Stream<String> stream = Stream.of("aa", "zz", "xx");
//输出stream中的内容
System.out.println(Arrays.toString(stream.toArray())); //[aa, bb, cc]
//方式二: 使用Arrays的静态方法stream完成
Stream<String> stream2 = Arrays.stream(strArr);
System.out.println(Arrays.toString(stream2.toArray()));
}
}
11. Stream中的forEach方法
/*
在Stream中,有一个方法叫做foreach,可以对流中的元素进行逐一处理。
void forEach(Consumer action): 该方法用来对流中元素进行逐一处理, 参数表示如何进行处理。
回忆Consumer表示消费者,里面有一个抽象方法accept,可以去消费一个数据。
void accept(T t): 用来消费一个数据(使用一个数据)
因为forEach方法参数是函数式接口Consumer,所以我们可以传递Lambda表达式,表示的就是如何处理。
*/
public class Demo01Foreach {
public static void main(String[] args) {
//通过Stream的of方法获取一个Stream流
Stream<String> stream = Stream.of("aaaaa", "bb", "cccccc", "dd", "eeeee");
//使用forEach方法逐一处理里面的数据, 逐一打印
//Lambda表达式中的s表示的是集合中的每一个元素。
//stream.forEach(s -> System.out.println(s));
stream.forEach(System.out::println);
}
}
12. Stream中的filter方法
/*
在Stream中,有一个方法叫做Filter,可以对流中的内容进行筛选(过滤)
Stream filter(Predicate predicate): 用来对流中的元素进行过滤。 参数Predicate表示过滤规则。
回忆Predicate是一个函数式接口, 这个函数式接口可以用来验证一个数据是否符合要求
抽象方法:
boolean test(T t)
filter参数是一个Predicate函数式接口,所以我们可以传递一个Lambda表达式, 这个Lambda表达式真正表示的
是Predicate中抽象方法test的内容(重写后), 我们要在Lambda表达式中定义筛选规则,如果Lambda表达式方法体
的结果是true就表示留下
*/
public class Demo02Filter {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aaaaa", "bb", "cccccc", "dd", "eeeee");
//对流中的内容进行筛选, 筛选出(留下)长度大于3的字符串
Stream<String> newStream = stream.filter(s -> s.length() > 3);
//使用forEach逐一处理,打印流中的每一个元素
newStream.forEach(s -> System.out.println(s));
}
}
13. Stream中的count方法
/*
在Stream中,还有一个方法,可以获取流的大小(流中元素的个数)
long count(): 返回流中元素的个数
*/
public class Demo03Count {
public static void main(String[] args) {
//获取一个流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");
//调用count方法,获取流中元素的个数
long count = stream.count();
System.out.println(count);
}
}
14. Stream中的limit方法
/*
在Stream中有一个方法,可以获取流中的前n个元素
Stream<T> limit(long n): 获取流中的前n个元素,并放入到一个新的流中返回。
*/
public class Demo04Limit {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd", "ee");
//Stream<T> limit(long n): 获取流中的前n个元素
Stream<String> newStream = stream.limit(3);
//使用forEach进行逐一处理
newStream.forEach(s -> System.out.println(s));
}
}
15. Stream中的skip方法
/*
在Stream中,有一个方法可以跳过流中的前n个元素,获取剩下的元素。
Stream<T> skip(long n): 跳过前n个元素,获取剩下的元素并放入到一个新的流中返回。
*/
public class Demo05Skip {
public static void main(String[] args) {
//获取流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd", "ee");
//Stream<T> skip(long n): 跳过前n个元素
Stream<String> newStream = stream.skip(3);
//打印新的流中的每一个元素
newStream.forEach(System.out::println);
}
}
16. Stream中的concat方法
/*
在Stream中,有一个静态方法,可以对两个流进行合并。
static Stream concat(Stream a, Stream b):对两个流进行合并, 返回合并后新的流。
*/
public class Demo06Concat {
public static void main(String[] args) {
//获取两个流
Stream<String> streamOne = Stream.of("aa", "bb");
Stream<String> streamTwo = Stream.of("cc", "dd");
//对这两个流进行合并
Stream<String> stream = Stream.concat(streamOne, streamTwo);
//输出合并后的流中的每一个元素
stream.forEach(System.out::println);
}
}
17. Stream中的map方法
/*
在Stream中,有一个方法,可以将流中的元素映射到一个新的流中。
映射表示的意思就是将原来流中的每一个元素进行处理,然后保存到一个新的流中。
原来的流:"10", "20", "30"
映射后流: 10, 20, 30
Stream中用于映射的方法:
Stream map(Function mapper): 可以将原来流中的内容映射到新的流中。 参数Function表示映射规则
回忆Function是一个函数式接口, 可以接收一个数据并产出一个结果。
抽象方法:
R apply(T t): 接收一个数据,产出结果。
因为参数Function是一个函数式接口,所以我们可以传递Lambda表达式, 这个Lambda表达式表示的是Function中的
抽象方法apply的内容。 我们要在Lambda表达式中定义映射规则。
*/
public class Demo07Map {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("10", "20", "30");
//将原来stream流中的每一个元素变成数字,然后放入到新的流中(将原来流中的元素映射到新的流)
//Stream<Integer> newStream = stream.map(s -> Integer.parseInt(s));
Stream<Integer> newStream = stream.map(Integer::parseInt);
//输出新的流中的内容
newStream.forEach(System.out::println);
}
}
19. Stream流的注意事项
/*
注意:
1. Stream流中的非终结方法返回的都是Stream对象, 返回的Stream是一个新的Stream
2. Stream流只能一次性使用,不能多次操作。
*/
public class Demo01Attention {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bb", "cc");
Stream<String> newStream = stream.limit(1);
//对比stream和newStream的地址值是否一样
//System.out.println(stream == newStream);
stream.count();
}
}
20. 使用传统方式操作集合的练习
/*
现在有两个ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建Person 对象;
7. 打印整个队伍的Person对象信息。
*/
public class Demo01StreamTest {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
one.add("欧阳锋");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//1. 第一个队伍只要名字为3个字的成员姓名;
List<String> oneA = new ArrayList<>();
//遍历one,拿到里面的每一个元素进行判断,如果长度是3,那么就添加到oneA中
for (String s : one) {
if(s.length() == 3) {
oneA.add(s);
}
}
//2. 第一个队伍筛选之后只要前3个人;
List<String> oneB = new ArrayList<>();
//遍历oneA集合, 只遍历三次,获取元素添加到oneB中。
for(int i = 0; i < 3; i++) {//0 1 2
String s = oneA.get(i);//拿到遍历到的元素
oneB.add(s);
}
//3. 第二个队伍只要姓张的成员姓名;
List<String> twoA = new ArrayList<>();
//遍历two,按到里面的每一个元素进行判断,如果是以张开头,那么就添加到twoA中
for (String s : two) {
if(s.startsWith("张")) {
twoA.add(s);
}
}
//4. 第二个队伍筛选之后不要前2个人;
List<String> twoB = new ArrayList<>();
//遍历twoA, 跳过前两次循环, 把遍历到的元素添加到twoB中
for(int i = 2; i < twoA.size(); i++) {
//拿到遍历到的元素
String s = twoA.get(i);
//添加
twoB.add(s);
}
//5. 将两个队伍合并为一个队伍;将twoB和oneB合并到一个集合中
List<String> totalList = new ArrayList<>();
totalList.addAll(oneB);//将oneB中的所有的元素添加到totalList中
totalList.addAll(twoB);
//6. 根据姓名创建Person 对象;
//定义集合,保存Person, 根据原来集合中的姓名创建Person对象, 并将Person对象保存到新的集合 中。
List<Person> personList = new ArrayList<>();
//遍历totalList,拿到里面的每一个姓名,根据姓名创建一个Person对象并添加到新的集合
for (String name : totalList) {
personList.add(new Person(name));
}
//7. 打印整个队伍的Person对象信息。
for (Person p : personList) {
System.out.println(p);
}
}
}
public class Person {
private String name;
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public Person(String name) {
this.name = name;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
21. Stream流操作集合的练习
/*
现在有两个ArrayList 集合存储队伍当中的多个成员姓名,要求使用Stream流实现
下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建Person 对象;
7. 打印整个队伍的Person对象信息。
*/
public class Demo02StreamTest {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
one.add("欧阳锋");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//1. 第一个队伍只要名字为3个字的成员姓名;
//2. 第一个队伍筛选之后只要前3个人;
Stream<String> streamOne = one.stream().filter(s -> s.length() == 3).limit(3);
//3. 第二个队伍只要姓张的成员姓名;
//4. 第二个队伍筛选之后不要前2个人;
Stream<String> streamTwo = two.stream().filter(s -> s.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍;
//6. 根据姓名创建Person 对象;
// 根据原来Stream流中的每一个姓名创建一个Person对象,并放入到新的流中。 就是将每一个姓名变成Person对象映射到新的流中
//7. 打印整个队伍的Person对象信息。
Stream.concat(streamOne, streamTwo).map(Person::new).forEach(System.out::println);
}
}
22. 将Stream中的元素收集到集合
/*
将Stream流中的数据收集出来,流中的数据可以收集到集合中,也可以收集到数组中(可以将流转成集合,也可以将流转成数组)
如何将流中的元素收集到集合中?
我们可以使用Stream中的方法collect去完成
Stream中用于收集的方法:
R collect(Collector collector):可以将流中的数据收集到集合。 参数Collector表示收集到哪种集合。Collector是一个接口,如果要传递需要传递Collector实现类对象, 这个实现类对象不能由我们自己去new,要通过Collectors工具类的静态方法进行获取, 使用不同方法获取的Collector,表示收集到了不同的集合中。
static Collector toList():如果使用toList获取的Collector对象,表示将数据收集到List集合中。
static Collector toSet()::如果使用toSet获取的Collector对象,表示将数据收集到Set集合中。
*/
public class Demo01StreamData {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");
//将stream流中的数据收集到List集合
//List<String> list = stream.collect(Collectors.toList());
//System.out.println(list);
//将stream流中的数据收集到Set集合
Set<String> set = stream.collect(Collectors.toSet());
System.out.println(set);
}
}
23. 将流中的内容收集到数组中
/*
将流中的元素收集到数组中。
我们可以使用Stream中的toArray方法进行收集
Object[] toArray(): 将流中的数据收集到数组, 返回Object[]
*/
public class Demo02StreamData {
public static void main(String[] args) {
//获取流
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");
//调用toArray方法,将流中的元素收集到数组中
Object[] objs = stream.toArray();
//打印数组
System.out.println(Arrays.toString(objs));
}
}
文章源自JAVA秀-https://www.javaxiu.com/736.html继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html

资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
评论