先说明,jdk8增加了一个包java.util.function,里面存放的都是新增的函数式接口,方便用lambda表达式重写其抽象方法
下面列举三个常见的函数式接口,下行是其抽象方法
Consumer
void accep(T t)接收一个参数,使用它
IntConsumer接受一个int类型的输入参数,无返回值 。
void accept(int value)接收一个int类型参数,使用它
Supplier
T get()返回一个T类型的对象
jdk8在Iterable接口中增加了defalut修饰的forEach()方法,用来遍历
先看下Iterable接口的源码
public interface Iterable {
Iterator iterator();
default void forEach(Consumer super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
forEach方法,接收一个Consumer类型的参数action,然后调用增强for循环对容器对象使用action.accept方法
咱们再来看Consumer接口的源码
@FunctionalInterface
public interface Consumer {
void accept(T t);//抽象方法
default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
accept为抽象方法,需要重写
到此我们知道怎么使用forEach来遍历集合了
要先调用容器的forEach方法,重写Consumer接口的accept方法
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ForEachTest03 {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(3);
list.add(5);
list.add(-1);
// 使用forEach方法遍历,实验匿名内部类的方式重写Consumer接口的accept方法
list.forEach(new Consumer() {
@Override
public void accept(Integer t) {
System.out.print(t + " ");
}
});
System.out.println();
// 使用lambda方式重写函数式接口的抽象方法更简洁
list.forEach((i) -> {
System.out.print(i + " ");
});
}
}
out:
3 5 -1
3 5 -1
方法引用指 通过方法的名字来指向一个方法。
方法引用的作用主要是简化lambda表达式,当lambda表达式只执行一个方法时,可使用方法引用简写lambda表达式
语法: 使用两个冒号 ::
有四种情况:
静态方法引用
类名::方法名
某个对象的引用,
对象实例::方法名
构造方法引用
构造方法,类名::new
特定类的任意对象的方法引用, 这个方法引用的使用需要注意,自定义类中无参数的方法可以使用,比如toString,hashCode等,或者compareTo等特定方法也可以使用,还没搞清楚什么原理呢,建议慎用,正常写就好了
类名::方法名
下面来示例:任意对象的方法引用
list.forEach((i)->System.out.println(i));
list.forEach(System.out::println);//System.out
示例:静态方法的方法引用
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class Test05 {
public static void main(String[] args) {
Set set1 = new TreeSet<>(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
});
Set set = new TreeSet<>(Integer::compareTo);
set.add(3);
set.add(6);
set.add(0);
for (Integer i : set) {
System.out.println(i);
}
}
}
out:
0
3
6
示例构造方法的引用,以下示例四种引用方式
import java.util.function.Supplier;
public class Student {
public String name;
public static Student creatStudent(Supplier s) {
System.out.println("通过方法引用创建对象");
return s.get();
}
public static void eat(Student student) {
System.out.println("Student " + student.getName() + "is eating");
}
public void drink(Student s) {
System.out.println("student" + s.getName() + "drink something");
}
public void study() {
System.out.println("the student" + this.getName() + " has studyed 5 hours");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("this student's name is " + name);
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
@Override
public String toString() {
System.out.println("Student [name=" + name + "]");
return "Student [name=" + name + "]";
}
}
//测试类
import java.util.Arrays;
import java.util.List;
public class Test06 {
public static void main(String[] args) {
// 构造方法引用
Student s1 = Student.creatStudent(Student::new);
Student s2 = Student.creatStudent(Student::new);
s1.setName("张三");
s2.setName("李四");
Student[] ss = { s1, s2 };
// 静态方法引用
List listStu = Arrays.asList(ss);
listStu.forEach(Student::eat);
// 特定对象的方法引用
listStu.forEach(s1::drink);
// 特定类任意对象的特定方法
listStu.forEach(Student::toString);
listStu.forEach(Student::study);
}
}
out:
通过方法引用创建对象
通过方法引用创建对象
this student's name is 张三
this student's name is 李四
Student 张三is eating
Student 李四is eating
student张三drink something
student李四drink something
Student [name=张三]
Student [name=李四]
the student张三 has studyed 5 hours
the student李四 has studyed 5 hours