Lambda 表达式练习
Lambad表达式、函数式接口、带泛型函数式接口的使用
练习1
@RunWith(SpringRunner.class)
@SpringBootTest
public class PlatformApplicationTests {
private Logger logger = LoggerFactory.getLogger(EntOrderRestController.class);
@Test
public void contextLoads() {
//Predicate 判断真假
Predicate<Integer> predicate = x -> x >= 175;
Student student = new Student("王大锤", 180, 18);
logger.info("王大锤有175吗?{}", predicate.test(student.getHeight()));
//Consumer 消费消息
Consumer<String> consumer = System.out::println;
consumer.accept(student.getName());
//Function 将T映射成R(转换功能)
Function<Student, String> name = Student::getName;
logger.info("姓名:" + name.apply(student));
// Supplier 生产消息
Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());
logger.info("生产消息:" + supplier.get());
List<Student> students = new ArrayList<>(3);
Student student1 = new Student("张三", 22, 175);
Student student2 = new Student("李四", 40, 180);
Student student3 = new Student("王五", 50, 185);
students.add(student1);
students.add(student2);
students.add(student3);
//UnaryOperator 一元操作 逻辑非(!)
UnaryOperator<Boolean> unaryOperator = ugl -> !ugl;
logger.info("一元操作返回值:" + unaryOperator.apply(true));
//BinaryOperator 二元操作 求两个数的乘积(*)
BinaryOperator<Integer> operator = (x, y) -> x * y;
Integer apply = operator.apply(2, 3);
logger.info("二元操作返回值:" + apply);
//演示函数式接口
test(() -> "你好,世界");
//惰性求值:只描述 Stream,操作的结果也是 Stream,这样的操作称为惰性求值。
//惰性求值可以像建造者模式一样链式使用,最后再使用及早求值得到最终结果。
//及早求值:得到最终的结果而不是 Stream,这样的操作称为及早求值。
//常用的流
//collect(Collectors.toList())
//将流转换为 list。还有 toSet(),toMap() 等。及早求值。
List<Student> collect = Stream.of(student1, student2, student3).collect(Collectors.toList());
logger.info("collect toList:"+collect);
System.out.println(collect);
//filter
//顾名思义,起过滤筛选的作用。内部就是 Predicate 接口。惰性求值。
//Predicate<Integer> predicate = x -> x >= 175;
List<Student> collect1 = students.stream().filter(a -> a.getHeight() > 180).collect(Collectors.toList());
logger.info("collect filter:"+collect1);
//map
//转换功能,内部就是 Function 接口。惰性求值
List<Integer> collect2 = students.stream().map(Student::getAge).collect(Collectors.toList());
logger.info("collect map:"+collect2);
// flatMap
//将多个 Stream 合并为一个 Stream。惰性求值
List<Student> collect3 = Stream.of(students, asList(student)).flatMap(stu -> stu.stream()).collect(Collectors.toList());
logger.info("collect flatMap:"+collect3);
//max 和 min
//我们经常会在集合中求最大或最小值,使用流就很方便。及早求值。
Optional<Student> max = students.stream().max(comparing(Student::getAge));
if (max.isPresent()) {
logger.info("最大值:"+max.get());
}
Optional<Student> min = students.stream().min(comparing(stu -> stu.getAge()));
if (min.isPresent()) {
logger.info("最小值:"+min.get());
}
//count
//统计功能,一般都是结合 filter 使用,因为先筛选出我们需要的再统计即可。及早求值
long count = students.stream().filter(stu -> stu.getAge() < 40).count();
logger.info("年龄小于40岁的人数是:"+count);
// reduce
//reduce 操作可以实现从一组值中生成一个值。在上述例子中用到的 count 、 min 和 max 方法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作。及早求值。
Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);
logger.info("reduce:"+reduce);
//转换成值
//** 收集器,一种通用的、从流生成复杂值的结构。** 只要将它传给 collect 方法,所有
//的流就都可以使用它了。标准类库已经提供了一些有用的收集器,以下示例代码中的收集器都是从 java.util.stream.Collectors 类中静态导入的。
Clbum clbum1=new Clbum("一班",students);
List<Student>students2=new ArrayList<>(students);
students2.remove(1);
Clbum clbum2=new Clbum("二班",students2);
Stream<Clbum> clbumStream = Stream.of(clbum1, clbum2);
System.out.println("一班平均年龄是:" + averageNumberOfStudent(students));
//转换成块
Map<Boolean,List<Student>>listMap=students.stream().
collect(Collectors.partitioningBy(stu->stu.getAge()>40));
logger.info("listMap:"+listMap);
//分组
Map<Integer,List<Student>>listMap1=students.stream().collect(Collectors.groupingBy(stu
->stu.getAge()));
logger.info("listMap1:"+listMap);
//字符串拼接
String names = students.stream().map(stu -> stu.getName()).collect(Collectors.joining(",", "[", "]"));
logger.info("names:"+names);
}
private double averageNumberOfStudent(List<Student> students) {
return students.stream().collect(averagingInt(Student::getAge));
}
public interface Worker {
String Work();
}
public void test(Worker worker) {
worker.Work();
}
class Student {
public String name;
public Integer height;
public Integer age;
public Student() {
}
public Student(String name, Integer age, Integer height) {
this.name = name;
this.height = height;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
class Clbum{
public String name;
public List<Student> student;
public Clbum() {
}
public Clbum(String name, List<Student> student) {
this.name = name;
this.student = student;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudent() {
return student;
}
public void setStudent(List<Student> student) {
this.student = student;
}
}
}
练习2
@SpringBootTest
class LambdaTest {
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, "赵六", 18, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
@Test
public void createTest() {
//根据年龄排序,年龄相同根据薪资
Collections.sort(emps, (x, y) -> {
if (x.getAge() == y.getAge()) {
return Double.compare(x.getSalary(), y.getSalary());
} else {
return Integer.compare(x.getAge(), y.getAge());
}
});
System.out.println("emps=" + emps);
}
/**
* 要求:
* ①声明函数式接口,接口中声明抽象方法,public String getValue();
* ②声明测试类,在类中编写方法使用接口作为参数,将每一个字符品转换成大写,并作为方法的返回值
* ③再将一个字符串的第2个和第4个索引位置进行截取子串
*/
@Test
public void test2() {
String str = "admin NBA Cba";
String valueF = getValueF(str,
x -> x.substring(0, 1).toUpperCase() + x.substring(1)
);
getValueJ(str, x -> (x.substring(0, 1).toUpperCase() + x.substring(1)));
getValueJ(str, (x) -> (x.substring(0, 1)));
System.out.println("valueF = " + valueF);
String valueF2 = getValueF(str,
x -> x.substring(1, 3)
);
System.out.println("valueF2 = " + valueF2);
}
public String getValueJ(String param, MyFunction1 function) {
return function.getValue(param);
}
public String getValueF(String str, MyFunction1 string2UpChar) {
return string2UpChar.getValue(str);
}
/**
* 要求:
* ①声明一个带两个泛型的函数式接口,泛型类型为<T,R> T为参数,R为返回值
* ②接口中声明对应抽象方法
* ③在测试类中声明方法,使得接口作为参数,计算两个long型参数的乘积
*/
@Test
public void test3() {
String calc = calc1(10L, 3L,
(a, b) -> new BigDecimal(a).multiply(new BigDecimal(b)).toString()
);
System.out.println("calc = " + calc);
}
public String calc1(Long l1, long l2, MyFunction3<Long, String> function3) {
return function3.calc(l1, l2);
}
}
@FunctionalInterface
interface MyFunction1 {
String getValue(String str);
}
@FunctionalInterface
interface MyFunction3<P, R> {
R calc(P t1, P t2);
}
@Data
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
class Employee {
private int id;
private String name;
private int age;
private double salary;
}