第18章_JDK8-17新特性拓展练习(lambda表达式,Stream API,Optional的使用)

news/2024/7/7 22:23:30

文章目录

  • 第18章_JDK8-17新特性拓展练习
    • lambda表达式
      • 1、Supplier接口练习1
      • 2、Supplier接口练习2
      • 3、Consumer接口和BiConsumer接口
      • 4、Consumer接口
      • 5、Comparator接口
      • 6、Comparator接口
      • 7、Comparator接口
      • 8、Predicate接口
      • 9、Predicate接口、Consumer接口
      • 10、Function接口
      • 11、BiFunction接口
      • 12、Comparator接口
      • 13、Function接口
      • 14、自定义函数式接口CurrentTimePrinter
      • 15、自定义函数式接口IntCalc
      • 16、自定义函数接口Call
      • 17、自定义函数式接口StringHandler
      • 18、自定义函数式接口LongHandler
    • Stream API
      • 19、map方法
      • 20、map方法和reduce方法
      • 21、filter方法
      • 22、filter方法和concat方法
      • 23、skip方法和concat方法
      • 24、filter方法
      • 25、Trader与Transaction
    • Optional的使用
      • 26、女朋友

第18章_JDK8-17新特性拓展练习


lambda表达式

1、Supplier接口练习1

使用Lambda表达式给Supplier接口赋值,实现产生1个100以内的整数功能。

import java.util.Random;
import java.util.function.Supplier;

public class Exercise1 {
    public static void main(String[] args) {
        Random random = new Random();
        Supplier<Integer> s = () -> random.nextInt(100);
        System.out.println(s.get());
    }
}

2、Supplier接口练习2

案例:

1、给出测试类代码如下:

package com.atguigu.exercise2;

import java.util.function.Supplier;

public class Exercise2 {
	public static <T> T getObj(Supplier<T> supplier) {
		return supplier.get();
	}

	public static void main(String[] args) {
		....
	}
}

2、分别使用lambda表达式获得以下对象:

  • 长度为5的String数组
  • 包含5个1-20(含1和20)之间随机数的HashSet集合
  • 一个代表2018年4月1日的Calendar对象
package com.atguigu.exercise2;

import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Random;
import java.util.function.Supplier;

public class Exercise2 {
	public static <T> T getObj(Supplier<T> supplier) {
		return supplier.get();
	}

	public static void main(String[] args) {
		String[] arr = getObj(() -> new String[5]);
		System.out.println(Arrays.toString(arr));
		
		Random rand = new Random();
		HashSet<Integer> nums = getObj(() -> {
			HashSet<Integer> set = new HashSet<Integer>();
			while(set.size()<5){
				set.add(rand.nextInt(20)+1);
			}
			return set;
		});
		System.out.println(nums);
		
		GregorianCalendar obj = getObj(() -> new GregorianCalendar(2019,5,13));
		System.out.println(obj);
	}
}

3、Consumer接口和BiConsumer接口

(1)知识提要:

已知在JDK1.8中java.lang.Iterable接口中增加了一个默认方法:

  • public default void forEach(Consumer<? super T> action) 该方法功能是遍历Collection集合,并将传递给action参数的操作代码应用在每一个元素上。

因为Collection接口继承了Iterable接口,这就意味着所有Collection系列的接口都包含该方法。

已知:在JDK1.8中Map集合接口中增加了一个默认方法:

  • public default void forEach(BiConsumer<? super K,? super V> action):该方法功能是遍历Map集合,并将传递给action参数的操作代码应用在每一对(key,value)映射关系上。

(2)案例需求:

  • 创建一个ArrayList,并添加26个小写字母到list中,并使用forEach遍历输出
  • 创建一个HashMap,并添加如下编程语言排名和语言名称到map中,并使用forEach遍历输出
排名语言
1Java
2C
3Python
4C++
5C#

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;

public class Exercise3 {
    @Test
    public void test01(){
        ArrayList<Character> list = new ArrayList<>();
        for (int i = 0; i <26 ; i++) {
            list.add((char)('a' + i));
        }
        list.forEach(c -> System.out.print(c+" "));
        System.out.println();
    }

    @Test
    public void test02(){
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"Java");
        map.put(2,"C");
        map.put(3,"Python");
        map.put(4,"C++");
        map.put(5,"C#");

        map.forEach((key,value) -> System.out.println(key +":" + value));
    }
}

4、Consumer接口

案例:

1、给出测试类代码如下:

import java.util.HashMap;
import java.util.function.Consumer;

public class Exercise4 {
	public static <T> void doJob(T t, Consumer<T> consumer) {
		consumer.accept(t);
	}

	public static <T> void doJob(T t, Consumer<T> consumer1, Consumer<T> consumer2) {
		consumer1.andThen(consumer2).accept(t);
	}

	public static void main(String[] args) {
		HashMap<String, Integer> map = new HashMap<>();

		// key:姓名 value:成绩
		map.put("岑小村", 59);
		map.put("谷天洛", 82);
		map.put("渣渣辉", 98);
		map.put("蓝小月", 65);
		map.put("皮几万", 70);
		
	}
}

2、分别使用lambda表达式完成以下需求

  • 打印谷天洛的分数
  • 打印最高分
  • 分别以60分和70分为及格线,打印及格的人的名字(组合型消费)
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class Exercise4 {
	public static <T> void doJob(T t, Consumer<T> consumer) {
		consumer.accept(t);
	}

	public static <T> void doJob(T t, Consumer<T> consumer1, Consumer<T> consumer2) {
		consumer1.andThen(consumer2).accept(t);
	}

	public static void main(String[] args) {
		HashMap<String, Integer> map = new HashMap<>();

		// key:姓名 value:成绩
		map.put("岑小村", 59);
		map.put("谷天洛", 82);
		map.put("渣渣辉", 98);
		map.put("蓝小月", 65);
		map.put("皮几万", 70);
		
	    //打印谷天洛的分数
        doJob(map, (m) -> System.out.println("谷天洛的分数:" + m.get("谷天洛")));

        //打印最高分
        doJob(map, (m) -> System.out.println("最高分:" + Collections.max(m.values())));

        //打印及格的人的名字
        doJob(map, (m) -> {
            System.out.print("60分及格的人:");
            for (Map.Entry<String, Integer> entry : m.entrySet()) {
                if (entry.getValue()>=60){
                    System.out.print(entry.getKey()+" ");
                }
            }
            System.out.println();
        }, (m) -> {
            System.out.print("70分及格的人:");
            for (Map.Entry<String, Integer> entry : m.entrySet()) {
                if (entry.getValue()>=70){
                    System.out.print(entry.getKey()+" ");
                }
            }
            System.out.println();
        });
	}
}

5、Comparator接口

(1)定义员工类Employee:包含属性id、姓名、年龄、工资,属性私有化,提供有参构造,get/set方法,重写toString方法。

(2)调用Collections.sort()方法,通过定制排序比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda表达式作为参数传递。

public class Employee {
    private int id;
    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}
public class Exercise5 {
    public static void main(String[] args) {
        List<Employee> emps = Arrays.asList(
                new Employee(101, "张三", 18, 9999.99),
                new Employee(102, "李四", 59, 6666.66),
                new Employee(103, "王五", 28, 3333.33),
                new Employee(104, "赵六", 8, 7777.77),
                new Employee(105, "田七", 38, 5555.55)
        );

        Collections.sort(emps, (e1, e2) -> {
            if(e1.getAge() == e2.getAge()){
                return e1.getName().compareTo(e2.getName());
            }else{
                return -Integer.compare(e1.getAge(), e2.getAge());
            }
        });

        for (Employee emp : emps) {
            System.out.println(emp);
        }
    }
}

6、Comparator接口

(1)定义学生类Student:包含属性name(姓名)和score(成绩),属性私有化,提供有参构造,get/set方法,重写toString方法。

(2)在测试类中,将五名学生添加到ArrayList集合

(3)使用Collections.sort(List list, Comparator<? super T> c)方法将学生成绩从小到大进行排序,分别使用以下三种形式实现:

  • 使用匿名内部类
  • 使用Lambda表达式
  • 使用方法引用 //tips:借助Comparator接口中静态方法comparingInt()方法

学生信息与成绩如下:

姓名数学
谢霆锋85
章子怡63
刘亦菲77
黄晓明33
岑小村92
public class Student {
    private String name;
    private int score;

    public Student() {
    }

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" + "name='" + name + '\'' + ", score=" + score + '}';
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Exercise6 {
    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("谢霆锋", 85));
        list.add(new Student("章子怡", 63));
        list.add(new Student("刘亦菲", 77));
        list.add(new Student("黄晓明", 33));
        list.add(new Student("岑小村", 92));

        // 使用匿名内部类将成绩从小到大排序
        Collections.sort(list, new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });

        // 使用Lambda为英语成绩从小到大排序
        Collections.sort(list, (o1, o2) -> o1.getScore() - o2.getScore());

        // 借助comparingInt()使用方法引用
        Collections.sort(list, Comparator.comparingInt(Student::getScore));

        System.out.println(list);
    }
}

7、Comparator接口

案例:

​ 1、定义学生类:
​ (1)成员变量 姓名:String name;
​ (2)成员变量 成绩:int score;
​ (3)无参及全参构造
​ (4)重写toString()

​ 2、在测试类中完成如下要求
​ (1)将五名学生添加到ArrayList集合
​ (2)使用Collections.sort(List list, Comparator<? super T> c)方法将学生成绩从小到大进行排序,分别使用以下三种形式实现:
​ a、使用匿名内部类
​ b、使用Lambda表达式
​ c、使用方法引用 //tips:借助Comparator接口中静态方法comparingInt()方法

​ 3、学生信息与成绩如下:

姓名数学
谢霆锋85
章子怡63
刘亦菲77
黄晓明33
岑小村92
public class Student {
	private String name;
	private int score;
	
	public Student() {
	}

	public Student(String name, int score) {
		this.name = name;
		this.score = score;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student{" + "name='" + name + '\'' + ", score=" + score + '}';
	}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Exercise7 {
	public static void main(String[] args) {
		ArrayList<Student> list = new ArrayList<>();
		list.add(new Student("谢霆锋", 85));
		list.add(new Student("章子怡", 63));
		list.add(new Student("刘亦菲", 77));
		list.add(new Student("黄晓明", 33));
		list.add(new Student("岑小村", 92));

		// 使用匿名内部类将成绩从小到大排序
		Collections.sort(list, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				return o1.getScore() - o2.getScore();
			}
		});

		// 使用Lambda为英语成绩从小到大排序
		Collections.sort(list, (o1, o2) -> o1.getScore() - o2.getScore());

		// 借助comparingInt()使用方法引用
		Collections.sort(list, Comparator.comparingInt(Student::getScore));

		System.out.println(list);
	}
}

8、Predicate接口

(1)声明一个Employee员工类型,包含编号、姓名、性别,年龄,薪资。属性私有化,提供有参构造,get/set,重写toString。

(2)声明一个EmployeeSerice员工管理类

  • 包含一个private 的属性ArrayList all。
  • 包含public void add(Employee emp)方法,可以添加员工到all集合中
  • 包含public ArrayList get(Predicate p),即将满足p指定的条件的员工,添加到一个新的ArrayList 集合中返回。

(3)在测试类中创建EmployeeSerice员工管理类的对象,添加一些员工对象,之后调用get方法,分别获取:

  • 所有员工对象
  • 所有年龄超过35的员工
  • 所有薪资高于15000的女员工
  • 所有编号是偶数的员工
  • 名字是“张三”的员工
  • 年龄超过25,薪资低于10000的男员工

示例代码:

Employee类:

public class Employee{
    private int id;
    private String name;
    private char gender;
    private int age;
    private double salary;

    public Employee(int id, String name, char gender, int age, double salary) {
        super();
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.salary = salary;
    }
    public Employee() {
        super();
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", salary=" + salary
                + "]";
    }
}

员工管理类:

import java.util.ArrayList;
import java.util.function.Predicate;

public class EmployeeService{
    private ArrayList<Employee> all = new ArrayList<>();

    public void add(Employee emp){
        all.add(emp);
    }

    public ArrayList<Employee> get(Predicate<Employee> p){
        ArrayList<Employee> result = new ArrayList<Employee>();
        for (Employee emp : all) {
            if(p.test(emp)){
                result.add(emp);
            }
        }
        return result;
    }
}

测试类:

public class Exercise8 {
    public static void main(String[] args) {
        EmployeeService es = new EmployeeService();

        es.add(new Employee(1, "张三", '男', 33, 8000));
        es.add(new Employee(2, "翠花", '女', 23, 18000));
        es.add(new Employee(3, "无能", '男', 46, 8000));
        es.add(new Employee(4, "李四", '女', 23, 9000));
        es.add(new Employee(5, "老王", '男', 23, 15000));
        es.add(new Employee(6, "大嘴", '男', 23, 11000));

        System.out.println("所有员工对象:");
        es.get(e -> true).forEach(e -> System.out.println(e));
        System.out.println();

        System.out.println("所有年龄超过35的员工:");
        es.get(e -> e.getAge() > 35).forEach(e -> System.out.println(e));
        System.out.println();

        System.out.println("所有薪资高于15000的女员工:");
        es.get(e -> e.getSalary() > 15000 && e.getGender() == '女').forEach(e -> System.out.println(e));
        System.out.println();

        System.out.println("所有编号是偶数的员工:");
        es.get(e -> e.getId() % 2 == 0).forEach(e -> System.out.println(e));
        System.out.println();

        System.out.println("名字是“张三”的员工:");
        es.get(e -> "张三".equals(e.getName())).forEach(e -> System.out.println(e));
        System.out.println();

        System.out.println("年龄超过25,薪资低于10000的男员工:");
        es.get(e -> e.getAge() > 25 && e.getSalary() < 10000 && e.getGender() == '男').forEach(e -> System.out.println(e));
    }
}

9、Predicate接口、Consumer接口

案例:

​ 1、声明一个员工类型Employee,包含编号、姓名、薪资、年龄、性别,属性私有化,提供有参构造,get/set方法,重写toString方法。

​ 2、声明一个员工管理类,

​ (1)管理类中使用ArrayList,来存储所有员工对象

​ (2)声明public void add(Employee emp)方法,添加员工

​ (3)声明public ArrayList get(Predicate p)方法,可以根据条件筛选出符合要求的员工

​ (4)声明public void remove(Predicate p)方法,可以根据条件删除

​ (5)声明public void update(Consumer c)方法,对集合中的元素执行c指定的操作

​ 3、在测试类

​ (1)添加5个员工对象到管理的集合中

​ (2)筛选出

​ ①编号是偶数的员工

​ ②薪资低于10000的员工

​ ③年龄大于30岁的女员工

​ ④姓张的员工

​ ⑤所有员工

​ (3)删除

​ ①年龄大于30岁的女员工

​ ②删除“张三”这个员工

​ (4)给每个员工涨薪10%

public class Employee {
	private int id;
	private String name;
	private double salary;
	private int age;
	private char gender;
	public Employee(int id, String name, double salary, int age, char gender) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
		this.age = age;
		this.gender = gender;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public char getGender() {
		return gender;
	}
	public void setGender(char gender) {
		this.gender = gender;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", age=" + age + ", gender=" + gender
				+ "]";
	}
}

import java.util.ArrayList;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class EmployeeService {
	private ArrayList<Employee> list;
	
	public EmployeeService(){
		list = new ArrayList<Employee>();
	}
	
	public void add(Employee emp){
		list.add(emp);
	}
	
	public ArrayList<Employee> get(Predicate<Employee> p){
		ArrayList<Employee> all = new ArrayList<Employee>();
		for (Employee employee : list) {
			if(p.test(employee)){
				all.add(employee);
			}
		}
		return all;
	}
	
	public void remove(Predicate<Employee> p){
		Iterator<Employee> iterator = list.iterator();
		while(iterator.hasNext()){
			Employee next = iterator.next();
			if(p.test(next)){
				iterator.remove();
			}
		}
	}
	
	public void update(Consumer<Employee> c){
		for (Employee employee : list) {
			c.accept(employee);
		}
	}
	
	public int size(){
		return list.size();
	}
}

import java.util.ArrayList;

import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;

public class Exercise9 {
	private static EmployeeService es = new EmployeeService();
	@BeforeClass
	public static void test01(){
		es.add(new Employee(1, "张三", 8000, 23, '男'));
		es.add(new Employee(2, "王小二", 12000, 22, '男'));
		es.add(new Employee(3, "李四", 12000, 24, '女'));
		es.add(new Employee(4, "王五", 11000, 34, '女'));
		es.add(new Employee(5, "赵六", 6000, 34, '女'));
	}
	@Test
	public void testSize(){
		System.out.println("目前员工数量:" + es.size());
	}
	
	@Test
	public void testRemove1(){
		//删除年龄大于30岁的女员工
		System.out.println("删除年龄大于30岁的女员工");
		es.remove(e->e.getAge()>30 && e.getGender()=='女');
	}
	
	@Test
	public void testRemove2(){
		//删除“张三”这个员工
		System.out.println("删除“张三”这个员工");
		es.remove(e->e.getName().startsWith("张"));
	}
	
	@Test
	public void testRemove3(){
		System.out.println("每个人涨薪资10%");
		es.update(e -> e.setSalary(e.getSalary()*1.1));
	}
	
	@After
	public void test(){
		System.out.println("编号是偶数的员工有:");
		ArrayList<Employee> list1 = es.get(e->e.getId()%2==0);
		for (Employee employee : list1) {
			System.out.println(employee);
		}
		
		System.out.println("薪资低于10000的员工有:");
		ArrayList<Employee> list2 = es.get(e->e.getSalary()<10000);
		for (Employee employee : list2) {
			System.out.println(employee);
		}
		
		System.out.println("年龄大于30岁的女员工有:");
		ArrayList<Employee> list3 = es.get(e->e.getAge()>30 && e.getGender()=='女');
		for (Employee employee : list3) {
			System.out.println(employee);
		}
		
		System.out.println("姓张的员工有:");
		ArrayList<Employee> list4 = es.get(e->e.getName().startsWith("张"));
		for (Employee employee : list4) {
			System.out.println(employee);
		}
		
		System.out.println("所有员工有:");
		ArrayList<Employee> list5 = es.get(e -> true);
		for (Employee employee : list5) {
			System.out.println(employee);
		}
		System.out.println();
	}
	
	
}

10、Function接口

案例:

1、已知学生成绩如下

姓名成绩
岑小村59
谷天洛82
渣渣辉98
蓝小月65
皮几万70

以学生姓名为key成绩为value创建集合并存储数据

2、使用lambda表达式分别将以下功能封装到Function对象中

(1)将Map<String,Integer>中value存到ArrayList中

(2)求Integer类型ArrayList中所有元素的平均数

3、使用Function对象求学生的平均值

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class Exercise10 {
	public static void main(String[] args) {
//		将学生姓名和成绩封装到map中
		HashMap<String,Integer> map = new HashMap<String, Integer>();
        map.put("岑小村", 59);
        map.put("谷天洛", 82);
        map.put("渣渣辉", 98);
        map.put("蓝小月", 65);
        map.put("皮几万", 70);
        
//        将Map<String,Integer>中value存到ArrayList<Integer>中
        Function<Map<String,Integer>,ArrayList<Integer>> f1 = (m)->{
            ArrayList<Integer> list = new ArrayList<>();
            list.addAll(m.values());
            return list;
        };
        
//        求Integer类型ArrayList中所有元素的平均数
        Function<ArrayList<Integer>,Double> f2 = (list)->{
            double sum = 0;
            for (Integer i : list) {
                sum+=i;
            }
            return sum/list.size();
        };
        
        //利用Function求平均成绩
        Double avg = f1.andThen(f2).apply(map);
        System.out.println("学生平均成绩为:"+avg);
	}
}

11、BiFunction接口

(1)知识提要

已知:在JDK1.8时Map接口如下方法:

public default void replaceAll(BiFunction<? super K,? super V,? extends V> function) 该方法功能是遍历Map集合,并将传递给function参数的操作代码应用在每一对(key,value)映射关系上,返回修改后的value。

public default void forEach(BiConsumer<? super K,? super V> action)该方法功能是遍历Map集合,并将传递给action参数的操作代码应用在每一对(key,value)映射关系上。

(2)案例需求

  • 声明一个Employee员工类型,包含属性编号、姓名、薪资,属性私有化,提供有参构造,get/set,重写toString。

  • 添加n个员工对象到一个HashMap<Integer,Employee>集合中,其中员工编号为key,员工对象为value。

  • 调用Map的forEach遍历集合

  • 调用Map的replaceAll方法,将其中薪资低于10000元的,薪资设置为10000。

  • 再次调用Map的forEach遍历集合查看结果

Employee类:

class Employee{
    private int id;
    private String name;
    private double salary;
    public Employee(int id, String name, double salary) {
        super();
        this.id = id;
        this.name = name;
        this.salary = salary;
    }
    public Employee() {
        super();
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
    }

}

测试类:

import java.util.HashMap;

public class Exercise11 {
    public static void main(String[] args) {
        HashMap<Integer,Employee> map = new HashMap<>();
        Employee e1 = new Employee(1, "张三", 8000);
        Employee e2 = new Employee(2, "李四", 9000);
        Employee e3 = new Employee(3, "王五", 10000);
        Employee e4 = new Employee(4, "赵六", 11000);
        Employee e5 = new Employee(5, "钱七", 12000);

        map.put(e1.getId(), e1);
        map.put(e2.getId(), e2);
        map.put(e3.getId(), e3);
        map.put(e4.getId(), e4);
        map.put(e5.getId(), e5);

        map.forEach((k,v) -> System.out.println(k+"="+v));
        System.out.println();

        map.replaceAll((k,v)->{
            if(v.getSalary()<10000){
                v.setSalary(10000);
            }
            return v;
        });
        map.forEach((k,v) -> System.out.println(k+"="+v));
    }
}

12、Comparator接口

(1)声明员工类,包含姓名、年龄、薪资,属性私有化,提供有参构造,get/set,重写toString。

(2)在测试类中,添加几个员工到一个ArrayList集合中

(3)调用集合的forEach方法,遍历集合元素,使用方法引用精简代码

(4)调用Collections集合工具类的sort(List list, Comparator<? super T> c)方法,按照薪资排序,使用方法引用精简代码

(5)调用Collections集合工具类的sort(List list, Comparator<? super T> c)方法,按照年龄排序,使用方法引用精简代码

public class Employee {
    private String name;
    private int age;
    private double salary;

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    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;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Exercise12 {
    public static void main(String[] args) {
        ArrayList<Employee> list = new ArrayList<>();
        list.add(new Employee("张三",23,10000.0));
        list.add(new Employee("李四",24,8000.0));
        list.add(new Employee("王五",25,11000.0));

        System.out.println("员工如下:");
        list.forEach(System.out::println);

        System.out.println("按照薪资排序如下:");
        Collections.sort(list, Comparator.comparingDouble(Employee::getSalary));
        list.forEach(System.out::println);

        System.out.println("按照年龄排序如下:");
        Collections.sort(list, Comparator.comparingInt(Employee::getAge));
        list.forEach(System.out::println);
    }
}

13、Function接口

已知有如下方法,可以实现创建一个长度为2的n次的数组

	//createArray()的作用是,创建一个长度为2的n次方的数组
	public static <R> R[] createArray(Function<Integer,R[]> fun,int length){
		int n = length - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        length = n < 0 ? 1 : n + 1;
		return fun.apply(length);
	}

使用上面的方法,实现创建一个长度为10的数组,查看返回的数组长度。

import java.util.function.Function;

public class Exercise13 {
    //createArray()的作用是,创建一个长度为2的n次方的数组
    public static <R> R[] createArray(Function<Integer,R[]> fun, int length){
        int n = length - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        length = n < 0 ? 1 : n + 1;
        return fun.apply(length);
    }

    public static void main(String[] args) {
        String[] array = createArray(String[]::new, 10);
        System.out.println(array.length);//16
    }
}

14、自定义函数式接口CurrentTimePrinter

案例:

1、定义一个函数式接口CurrentTimePrinter,其中抽象方法void printCurrentTime(),使用注解@FunctionalInterface

2、在测试类中定义public static void showLongTime(CurrentTimePrinter timePrinter),该方法的预期行为是使用timePrinter打印当前系统时间

3、测试showLongTime(),通过lambda表达式完成需求

(1)实现一:打印当前系统时间毫秒值,用System. currentTimeMillis()

(2)实现二:打印当前系统时间,用Date

(3)实现三:打印本地化当前系统时间,用LocalDateTime

  • 方式1:
@FunctionalInterface
public interface CurrentTimePrinter{
    void printCurrentTime();
}
package com.atguigu.exercise14;

import java.time.LocalDateTime;
import java.util.Date;

public class Exercise14 {
    public static void main(String[] args) {
        CurrentTimePrinter c1 = () -> System.out.println(System.currentTimeMillis());
        CurrentTimePrinter c2 = () -> System.out.println(new Date());
        CurrentTimePrinter c3 = () -> System.out.println(LocalDateTime.now());

        c1.printCurrentTime();
        c2.printCurrentTime();
        c3.printCurrentTime();
    }
}
  • 方式2:
import java.time.LocalDateTime;
import java.util.Date;

public class Exercise14 {
	
	public static void main(String[] args) {
		showLongTime(() -> System.out.println(System.currentTimeMillis()));
		showLongTime(() -> System.out.println(new Date()));
		showLongTime(() -> System.out.println(LocalDateTime.now()));
	}
	
	public static void showLongTime(CurrentTimePrinter timePrinter){
		timePrinter.printCurrentTime();
	}
}
@FunctionalInterface
interface CurrentTimePrinter{
	void printCurrentTime();
}

15、自定义函数式接口IntCalc

案例:

1、定义一个函数式接口IntCalc,其中抽象方法int cal(int a , int b),使用注解@FunctionalInterface
2、在测试类中定义public static void getProduct(int a , int b ,IntCalc tools), 该方法的预期行为打印使用tools的cal(a,b)的计算结果
3、测试getProduct(),通过lambda表达式完成需求,其中a =1,b = 2

(1)实现一:求a,b的和

(2)实现二:求a,b的差

(3)实现三:求a,b的积

(4)实现四:求a,b的商

(5)实现五:求a,b的按位与

(6)实现六:求a<<b

public class Exercise15 {
	public static void main(String[] args) {
		getProduct(1,2,(a,b) -> a+b);
		getProduct(1,2,(a,b) -> a-b);
		getProduct(1,2,(a,b) -> a*b);
		getProduct(1,2,(a,b) -> a/b);
		getProduct(1,2,(a,b) -> a&b);
		getProduct(1,2,(a,b) -> a<<b);
	}
	
	public static void getProduct(int a , int b ,IntCalc tools){
		System.out.println("结果:" + tools.cal(a, b));
	}
}
@FunctionalInterface
interface IntCalc{
	int cal(int a , int b);
}

16、自定义函数接口Call

(1)声明函数式接口Call,并用@FunctionalInterface注解标记。Call接口包含抽象方法void call()。

(2)在测试类中使用Lambda表达式为Call接口的变量赋值,并调用call方法。分别实现如下功能:

  • 输出我爱尚硅谷
  • 输出你妈喊你回家吃饭
  • 输出宋老师喊你写代码
@FunctionalInterface
public interface Call {
    void call();
}
public class Exercise16 {
    public static void main(String[] args) {
        Call c1 = () -> System.out.println("我爱你尚硅谷");
        c1.call();

        Call c2 = () -> System.out.println("你妈喊你回家吃饭");
        c2.call();

        Call c3 = () -> System.out.println("宋老师喊你写代码");
        c3.call();
    }
}

17、自定义函数式接口StringHandler

①声明函数式接口StringHandler,接口中声明抽象方法:public String getValue(String str);

②声明类LambdaTest,类中编写方法使用接口作为参数。

③测试方法时,实现:

  • 将一个字符串首尾空格去掉,并返回

  • 将一个字符串转换成大写,并作为方法的返回值。

  • 将一个字符串的第2个到第4个索引位置进行截取子串。

@FunctionalInterface
interface StringHandler{
    String getValue(String str);
}

public class Exercise17 {
    public static void main(String[] args) {
        String trimStr = strHandler("\t\t\t 尚硅谷IT教育   ", (str) -> str.trim());
        System.out.println(trimStr);

        String upper = strHandler("abcdef", (str) -> str.toUpperCase());
        System.out.println(upper);

        String newStr = strHandler("世界那么大,我想去看看", (str) -> str.substring(2, 5));
        System.out.println(newStr);
    }

    //需求:用于处理字符串
    public static String strHandler(String str, StringHandler mf){
        return mf.getValue(str);
    }
}

18、自定义函数式接口LongHandler

①声明一个带两个泛型的函数式接口,泛型类型为<T,R> : T 为参数,R 为返回值。

②接口中声明对应抽象方法:getValue,传入两个T类型的变量

③在LambdaTest类中声明方法op(),使用接口作为参数

④调用op()方法时,分别实现

  • 计算两个long型参数的和

  • 计算两个long型参数的乘积

@FunctionalInterface
interface LongHandler<T,R>{
    R getValue(T t1,T t2);
}

public class Exercise18 {
    public static void main(String[] args) {
        op(100L, 200L, (x, y) -> x + y);

        op(100L, 200L, (x, y) -> x * y);
    }

    //需求:对于两个 Long 型数据进行处理
    public static void op(Long l1, Long l2, LongHandler<Long, Long> mf){
        System.out.println(mf.getValue(l1, l2));
    }
}

Stream API

19、map方法

给定一个数字列表,如何返回一个由每个数的平方构成的列表呢?

例如,给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。

@Test
public void Exercise19(){
   Integer[] nums = new Integer[]{1,2,3,4,5};
   	
   Arrays.stream(nums).map((x) -> x * x).forEach(System.out::println);
}

20、map方法和reduce方法

怎样用 map 和 reduce 方法数一数流中有多少个Employee呢?

List<Employee> emps = Arrays.asList(
	new Employee(102, "李四", 59, 6666.66, Status.BUSY),
	new Employee(101, "张三", 18, 9999.99, Status.FREE),
	new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
	new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
	new Employee(104, "赵六", 8, 7777.77, Status.FREE),
	new Employee(104, "赵六", 8, 7777.77, Status.FREE),
	new Employee(105, "田七", 38, 5555.55, Status.BUSY)
);
	
@Test
public void Exercise20(){
	Optional<Integer> count = emps.stream().map((e) -> 1).reduce(Integer::sum);
	System.out.println(count.get());
}

21、filter方法

现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,

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("张声谷");

要求使用Stream方式进行以下若干操作步骤:

  1. 第一个队伍只要名字为3个字的成员姓名;

  2. 第一个队伍筛选之后只要前4个人;

  3. 第二个队伍只要姓张的成员姓名;

  4. 第二个队伍筛选之后不要前1个人;

  5. 将两个队伍合并为一个队伍;

  6. 根据姓名创建Student对象;Student类型包含name属性

  7. 打印整个队伍的Student对象信息。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Exercise21 {
	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("张声谷");

		// 第一个队伍只要名字为3个字的成员姓名;
		// 第一个队伍筛选之后只要前4个人;
		Stream<String> streamOne = one.stream().filter(s -> s.length() == 3).limit(6);

		// 第二个队伍只要姓张的成员姓名;
		// 第二个队伍筛选之后不要前1个人;
		Stream<String> streamTwo = two.stream().filter(s -> s.startsWith("张")).skip(1);

		// 将两个队伍合并为一个队伍;
		// 根据姓名创建Student对象;
		// 打印整个队伍的Student对象信息。
		Stream.concat(streamOne, streamTwo).map(Student::new).forEach(System.out::println);
	}
}

class Student {
	private String name;

	public Student() {
	}

	public Student(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return " Student {name='" + name + "'}";
	}
}

22、filter方法和concat方法

现在有两个 ArrayList 集合存储队伍当中的多个成员姓名:

//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");

//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");

还有Person类代码如下:

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

针对上述集合数据进行如下操作:

  • 第一个队伍只要名字为小于等于3个字的成员姓名;第一个队伍筛选之后只要前3个人;存储到一个新集合中。
  • 第二个队伍只要姓张的成员姓名;第二个队伍筛选之后去掉前2个人;存储到一个新集合中。
  • 将两个队伍合并为一个队伍;存储到一个新集合中,打印合并队伍后成员姓名。
  • 将两个队伍合并为一个队伍,并根据姓名创建 Person 对象;存储到一个新集合中,打印整个队伍的Person对象信息。

参考答案:

import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Exercise22 {
    public static void main(String[] args) {
        //第一支队伍
        ArrayList<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("石破天");
        one.add("石中玉");
        one.add("老子");
        one.add("庄子");
        one.add("洪七公");

        //第二支队伍
        ArrayList<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("赵丽颖");
        two.add("张三丰");
        two.add("尼古拉斯赵四");
        two.add("张天爱");
        two.add("张二狗");

        // 第一个队伍只要名字小于等于3个字的成员姓名;
        // 第一个队伍筛选之后只要前3个人;
        System.out.println("第一个队伍处理后结果:");
        one.stream().filter(s -> s.length() <= 3).limit(3).collect(Collectors.toList()).forEach(System.out::println);

        // 第二个队伍只要姓张的成员姓名;
        // 第二个队伍筛选之后去掉前2个人;
        System.out.println("第二个队伍处理后结果:");
       two.stream().filter(s -> s.startsWith("张")).skip(2).collect(Collectors.toList()).forEach(System.out::println);

        // 将两个队伍合并为一个队伍;存储到一个新集合中,打印合并队伍后成员姓名。
        System.out.println("两个队伍合并后结果:");
        Stream.concat(one.stream(), two.stream()).collect(Collectors.toList()).forEach(System.out::println);

//        将两个队伍合并为一个队伍;
        // 根据姓名创建Person对象;
        // 打印整个队伍的Person对象信息。
        System.out.println("两个队伍合并后,创建Person对象结果:");
        Stream.concat(one.stream(), two.stream()).map(Person::new).collect(Collectors.toList()).forEach(System.out::println);
    }
}

23、skip方法和concat方法

案例:

以下是某不知名机构评出的全球最佳影片及华人最佳影片前十名 :

全球
  1、 《教父》
  2、 《肖申克的救赎》
  3、 《辛德勒的名单》
  4、 《公民凯恩》
  5、 《卡萨布兰卡》
  6、 《教父续集》
  7、 《七武士》
  8、 《星球大战》
  9、 《美国美人》
  10、 《飞跃疯人院》
华人

1、 《霸王别姬》
  2、 《大闹天宫》
  3、 《鬼子来了》
  4、 《大话西游》
  5、 《活着》
  6、 《饮食男女》
  7、 《无间道》
  8、 《天书奇谭》
  9、 《哪吒脑海》
  10、 《春光乍泄》

开发提示:

(1)定义电影Film类,包含name属性,属性私有化,提供有参构造,get/set方法,重写toString方法。

(2)现将两个榜单中的影片名,分别按排名顺序依次存入两个ArrayList集合

(3)通过流的方式

  • 打印全球影片排行榜中的前三甲影片名

  • 打印华人影片排行榜中倒数5名的影片名

  • 将两个排行榜中的前5名挑出来共同存入新的集合

  • 以影片名为name创建Film对象并保存至集合

public class Film {
    private String name;

    public Film() {
    }

    public Film(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Film [name=" + name + "]";
    }
}
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Exercise23 {
    public static void main(String[] args) {
        // 将原始数据存入集合
        ArrayList<String> global = new ArrayList<>();
        global.add("《教父》");
        global.add("《肖申克的救赎》");
        global.add("《辛德勒的名单》");
        global.add("《公民凯恩》");
        global.add("《卡萨布兰卡》");
        global.add("《教父续集》");
        global.add("《七武士》");
        global.add("《星球大战》");
        global.add("《美国美人》");
        global.add("《飞跃疯人院》");

        ArrayList<String> china = new ArrayList<>();
        china.add("《霸王别姬》");
        china.add("《大闹天宫》");
        china.add("《鬼子来了》");
        china.add("《大话西游》");
        china.add("《活着》");
        china.add("《饮食男女》");
        china.add("《无间道》");
        china.add("《天书奇谭》");
        china.add("《哪吒脑海》");
        china.add("《春光乍泄》");

        // 1)打印全球影片排行榜中的前三甲影片名
        global.stream().limit(3).forEach(System.out::println);
        System.out.println();

        // 2)打印华人影片排行榜中倒数5名的影片名
        china.stream().skip(china.size() - 5).forEach(System.out::println);
        System.out.println();

        // 3)将两个排行榜中的前5名挑出来共同存入新的集合
        Stream.concat(global.stream().limit(5), china.stream().limit(5))
                .collect(Collectors.toList())
                .forEach(System.out::println);
        System.out.println();

        // 4)将所有影片以影片名为name创建Film对象并保存至集合
       Stream.concat(global.stream(), china.stream()).map(Film::new)
                .collect(Collectors.toList())
               .forEach(System.out::println);
    }
}

24、filter方法

我国有34个省级行政区,分别是:

23个省:

河北省、山西省、吉林省、辽宁省、黑龙江省、陕西省、甘肃省、青海省、山东省、福建省、浙江省、台湾省、河南省、湖北省、湖南省、江西省、江苏省、安徽省、广东省、海南省、四川省、贵州省、云南省。

4个直辖市:

北京市、天津市、上海市、重庆市。

5个自治区:

内蒙古自治区、新疆维吾尔自治区、[夏回族自治区、广西壮族自治区、西藏自治区

2个特别行政区:

香港特别行政区、澳门特别行政区

使用流:

1、统计三个字的省份的个数

2、统计名字中包含方位名词的省份(东西南北)的个数

3、打印名字中包含方位名词的普通省份(非自治区直辖市特别行政区)的名字

4、将所有的特殊省份(自治区直辖市特别行政区)提取出来并放到新数组中

import java.util.Arrays;
import java.util.stream.Stream;

public class Exercise24 {
	public static void main(String[] args) {
		String[] provinces = { "河北省", "山西省", "吉林省", "辽宁省", "黑龙江省", "陕西省", "甘肃省", "青海省", "山东省", "福建省", "浙江省", "台湾省",
				"河南省", "湖北省", "湖南省", "江西省", "江苏省", "安徽省", "广东省", "海南省", "四川省", "贵州省", "云南省", "北京市", "天津市", "上海市", "重庆市",
				"内蒙古自治区", "新疆维吾尔自治区", "宁夏回族自治区", "广西壮族自治区", "西藏自治区", "香港特别行政区", "澳门特别行政区" };

		// 1、统计三个字的省份的个数
		long threeCount = Stream.of(provinces).filter(s -> s.length() == 3).count();
		System.out.println("三个字的省份的个数:" + threeCount);

		// 2、统计名字中包含方位名词的省份(东西南北)的个数
		long count = Stream.of(provinces)
				.filter(s -> s.contains("东") || s.contains("西") || s.contains("南") || s.contains("北")).count();
		System.out.println("包含方位名词的省份(东西南北)的个数:" + count);

		// 3、打印名字中包含方位名词的普通省份(非自治区直辖市特别行政区)的名字
		System.out.println("包含方位名词的普通省份有:");
		Stream.of(provinces).filter(s -> s.contains("东") || s.contains("西") || s.contains("南") || s.contains("北"))
				.filter(s -> s.contains("省")).forEach(System.out::println);

		// 4、将所有的特殊省份(自治区直辖市特别行政区)提取出来并放到新数组中
		String[] pros = Stream.of(provinces).filter(s -> !s.contains("省")).toArray(String[]::new);
		System.out.println("新数组:" + Arrays.toString(pros));
	}
}

25、Trader与Transaction

现有Trader和Transaction两个类,完成如下需求:

  1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)

  2. 交易员都在哪些不同的城市工作过

  3. 查找所有来自剑桥的交易员,并按姓名排序

  4. 返回所有交易员的姓名字符串,按字母顺序排序

  5. 有没有交易员是在米兰工作的

  6. 打印生活在剑桥的交易员的所有交易额

  7. 所有交易中,最高的交易额是多少

  8. 找到交易额最小的交易

具体如下:

//交易员类
public class Trader {

	private String name;
	private String city;

	public Trader() {
	}

	public Trader(String name, String city) {
		this.name = name;
		this.city = city;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	@Override
	public String toString() {
		return "Trader [name=" + name + ", city=" + city + "]";
	}

}

//交易类
public class Transaction {

	private Trader trader;
	private int year;
	private int value;

	public Transaction() {
	}

	public Transaction(Trader trader, int year, int value) {
		this.trader = trader;
		this.year = year;
		this.value = value;
	}

	public Trader getTrader() {
		return trader;
	}

	public void setTrader(Trader trader) {
		this.trader = trader;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Transaction [trader=" + trader + ", year=" + year + ", value="
				+ value + "]";
	}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.Before;
import org.junit.Test;

public class Exercise25 {
	
	List<Transaction> transactions = null;
	
	@Before
	public void before(){
		Trader raoul = new Trader("Raoul", "Cambridge");
		Trader mario = new Trader("Mario", "Milan");
		Trader alan = new Trader("Alan", "Cambridge");
		Trader brian = new Trader("Brian", "Cambridge");
		
		transactions = Arrays.asList(
				new Transaction(brian, 2011, 300),
				new Transaction(raoul, 2012, 1000),
				new Transaction(raoul, 2011, 400),
				new Transaction(mario, 2012, 710),
				new Transaction(mario, 2012, 700),
				new Transaction(alan, 2012, 950)
		);
	}
	
	//1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
	@Test
	public void test1(){
		transactions.stream()
					.filter((t) -> t.getYear() == 2011)
					.sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
					.forEach(System.out::println);
	}
	
	//2. 交易员都在哪些不同的城市工作过?
	@Test
	public void test2(){
		transactions.stream()
					.map((t) -> t.getTrader().getCity())
					.distinct()
					.forEach(System.out::println);
	}
	
	//3. 查找所有来自剑桥的交易员,并按姓名排序
	@Test
	public void test3(){
		transactions.stream()
					.filter((t) -> t.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getTrader)
					.sorted((t1, t2) -> t1.getName().compareTo(t2.getName()))
					.distinct()
					.forEach(System.out::println);
	}
	
	//4. 返回所有交易员的姓名字符串,按字母顺序排序
	@Test
	public void test4(){
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.forEach(System.out::println);
		
		System.out.println("-----------------------------------");
		
		String str = transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.reduce("", String::concat);
		
		System.out.println(str);
		
		System.out.println("------------------------------------");
		
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.flatMap(TestTransaction::filterCharacter)
					.sorted((s1, s2) -> s1.compareToIgnoreCase(s2))
					.forEach(System.out::print);
	}
	
	public static Stream<String> filterCharacter(String str){
		List<String> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch.toString());
		}
		
		return list.stream();
	}
	
	//5. 有没有交易员是在米兰工作的?
	@Test
	public void test5(){
		boolean bl = transactions.stream()
					.anyMatch((t) -> t.getTrader().getCity().equals("Milan"));
		
		System.out.println(bl);
	}
	
	
	//6. 打印生活在剑桥的交易员的所有交易额
	@Test
	public void test6(){
		Optional<Integer> sum = transactions.stream()
					.filter((e) -> e.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getValue)
					.reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
	
	
	//7. 所有交易中,最高的交易额是多少
	@Test
	public void test7(){
		Optional<Integer> max = transactions.stream()
					.map((t) -> t.getValue())
					.max(Integer::compare);
		
		System.out.println(max.get());
	}
	
	//8. 找到交易额最小的交易
	@Test
	public void test8( ){
		Optional<Transaction> op = transactions.stream()
					.min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()));
		
		System.out.println(op.get());
	}

}

Optional的使用

26、女朋友

(1)声明一个Girl类型,包含姓名(String)属性

(2)声明一个Boy类型,包含姓名(String),女朋友(Girl)属性

(3)在测试类中声明方法public static Optional getGirlFriend(Boy boy)

(4)在测试类的main中创建一个Boy对象,并调用getGirlFriend方法获取他的女朋友。

如果他有女朋友,显示他女朋友名称;

如果他没有女朋友,他的女朋友默认为“嫦娥”,即只能欣赏“嫦娥”了

public class Girl {
    private String name;

    public Girl(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Girl [name=" + name + "]";
    }

}


package com.atguigu.exercise26;

public class Boy {
    private String name;
    private Girl girlFriend;

    public Boy(String name, Girl girlFriend) {
        super();
        this.name = name;
        this.girlFriend = girlFriend;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Girl getGirlFriend() {
        return girlFriend;
    }

    public void setGirlFriend(Girl girlFriend) {
        this.girlFriend = girlFriend;
    }

    @Override
    public String toString() {
        return "Boy [name=" + name + ", girlFriend=" + girlFriend + "]";
    }
}

测试类

import com.sun.istack.internal.NotNull;

import java.util.Optional;

public class Exercise26 {
    public static Optional<Girl> getGirlFriend(Boy boy){
        if(boy == null){
            return Optional.empty();
        }
        return Optional.ofNullable(boy.getGirlFriend());
    }

    public static void main(String[] args) {
        //		Boy boy = new Boy("张三",null);
        Boy boy = new Boy("张三",new Girl("翠翠"));
        Girl girl = getGirlFriend(boy).orElse(new Girl("嫦娥"));
        Optional.of(girl).ifPresent(System.out::println);
    }
}

在这里插入图片描述


http://lihuaxi.xjx100.cn/news/1974208.html

相关文章

backtrader策略库:强化学习二:应用

点此获取backtrader技术教程 前一个帖子介绍了梯度提升gradient ascent的概念&#xff0c;本文介绍如何使用梯度提升最大化回报函数。 文末有github源码链接。 In my last post we learned what gradient ascent is, and how we can use it to maximize a reward function. T…

IDA Pro 7.7和8.3共用方案

1.问题 IDA 8.3版本放出来后&#xff0c;我安装之后&#xff0c;把之前用的正好的7.7给卸载了&#xff0c;然后发现&#xff1a;IDA 8.3版本只能反编译x86和x64两个架构&#xff0c;而我又是arm和arm64的重度用户&#xff0c;只能把旧版下载回来。问题就出现在这里。 &#x…

【SpringBoot】SpringBoot 项目初始化方法

github 搜索 springboot 模板 github 搜索 springboot 模板&#xff0c;拉取现成代码。 SpringBoot 官方的模板生成器 SpringBoot 官方的模板生成器&#xff08;https://start.spring.io/&#xff09; 在 IDEA 开发工具中生成 这里我修改成阿里的镜像主要是要使用 Java8。 …

Scrcpy:掌握你的Android设备

Scrcpy&#xff1a;掌握你的Android设备 本文将介绍Scrcpy工具&#xff0c;它是一种强大的安卓设备控制工具&#xff0c;可以实现屏幕镜像、操作控制等功能。我们将探讨Scrcpy的基本原理和工作方式&#xff0c;并介绍如何使用Scrcpy连接和控制安卓设备。此外&#xff0c;我们还…

【Git】 取消上一次commit或push

一、取消上一次commit 如果你需要取消上一次的 Git 提交&#xff0c;有几个不同的方法可以实现。其中包括撤消提交、提交到新的分支、使用 Git 回滚等等。 下面介绍三种方法&#xff1a; 方法1&#xff1a;使用 Git reset 使用 Git reset 命令来取消上一次提交&#xff1a; …

【算法练习】leetcode算法题合集之栈和队列篇

普通栈 LeetCode20 有效的括号 LeetCode20 有效的括号 定义一个辅助map&#xff0c;判断字符串的字符是否在]})中。一旦是右括号就要弹出元素&#xff0c;判断匹配。 class Solution {public boolean isValid(String s) {if (s.length() % 2 1) {return false;}Map<Chara…

c++ 函数参数的传递

在 C++ 中,函数参数可以通过值传递、指针传递或引用传递的方式来传递。每种传递方式有其用途和行为特点。理解这些不同之处对于有效地使用 C++ 来说非常重要。 先大概了解一下各个指针的信息,再看实例 值传递(Pass by Value):创建实参的副本,函数中的改动不影响实际的变…

30天精通Nodejs--第二十二天:express-认证和授权

目录 引言理解JWT及其工作原理安装与引入JWT库生成JWT令牌验证JWT令牌注意事项与最佳实践结语引言 在现代Web应用开发中,JSON Web Tokens(JWT)作为一种轻量级、自包含且安全的标准,已被广泛用于实现用户身份验证和授权。尤其是在Node.js环境下的Express框架中,JWT提供了一…