1. 程式人生 > >jdk8新特性 forEach方法和方法引用

jdk8新特性 forEach方法和方法引用

先說明,jdk8增加了一個包java.util.function,裡面存放的都是新增的函式式介面,方便用lambda表示式重寫其抽象方法

下面列舉三個常見的函式式介面,下行是其抽象方法

 Consumer<T>代表了接受一個輸入引數並且無返回的操作

 void accep(T t)接收一個引數,使用它
 IntConsumer接受一個int型別的輸入引數,無返回值 。

void accept(int value)接收一個int型別引數,使用它
 Supplier<T>無引數,返回一個結果。

 T get()返回一個T型別的物件

forEach

 

jdk8在Iterable介面中增加了defalut修飾的forEach()方法,用來遍歷

先看下Iterable介面的原始碼

public interface Iterable<T> {
    Iterator<T> iterator();
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

forEach方法,接收一個Consumer型別的引數action,然後呼叫增強for迴圈對容器物件使用action.accept方法

咱們再來看Consumer介面的原始碼

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);//抽象方法
    default Consumer<T> 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<Integer> list = new ArrayList<>();
		list.add(3);
		list.add(5);
		list.add(-1);
		// 使用forEach方法遍歷,實驗匿名內部類的方式重寫Consumer介面的accept方法
		list.forEach(new Consumer<Integer>() {

			@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<Integer> set1 = new TreeSet<>(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return Integer.compare(o1, o2);
			}

		});
		Set<Integer> 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<Student> 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<Student> 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