Java를 배우는 비 Java 프로그래머로서 나는 현재 Supplier
및 Consumer
인터페이스에 대해 읽고 있습니다. 그리고 나는 그들의 사용법과 의미에 대해 머리를 감쌀 수 없습니다. 이 인터페이스를 언제, 왜 사용합니까? 누군가 나에게 이것에 대한 간단한 평신도 예제를 줄 수 있습니까? 나는 Doc 예제가 내 이해에 충분히 간결하지 않다는 것을 발견하고 있습니다.
Java를 배우는 비 Java 프로그래머로서 나는 현재 Supplier
및 Consumer
인터페이스에 대해 읽고 있습니다. 그리고 나는 그들의 사용법과 의미에 대해 머리를 감쌀 수 없습니다. 이 인터페이스를 언제, 왜 사용합니까? 누군가 나에게 이것에 대한 간단한 평신도 예제를 줄 수 있습니까? 나는 Doc 예제가 내 이해에 충분히 간결하지 않다는 것을 발견하고 있습니다.
답변:
이것은 공급자입니다 :
public Integer getInteger() {
return new Random().nextInt();
}
이것은 소비자입니다 :
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
따라서 평범한 용어로 공급자는 일부 값을 반환하는 메서드입니다 (반환 값에서와 같이). 반면 소비자는 (메서드 인수에서와 같이) 일부 값을 소비하고 이에 대해 일부 작업을 수행하는 메서드입니다.
이들은 다음과 같이 변형됩니다.
// new operator itself is a supplier, of the reference to the newly created object
Supplier<List<String>> listSupplier = ArrayList::new;
Consumer<String> printConsumer = a1 -> System.out.println(a1);
BiConsumer<Integer, Integer> sumConsumer = (a1, a2) -> System.out.println(a1 + a2);
사용법에 관해서는 매우 기본적인 예는 다음과 같습니다 Stream#forEach(Consumer)
. 반복중인 스트림에서 요소를 소비하고 각각에 대해 몇 가지 작업을 수행하는 소비자가 필요합니다. 아마도 인쇄 할 것입니다.
Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);
에서와 같은 기능적 인터페이스의 의미를 이해하는 데 어려움을 겪는 이유 java.util.function
는 여기에 정의 된 인터페이스가 의미가 없기 때문입니다! 그것들은 주로 의미론이 아니라 구조 를 나타 내기 위해 존재 합니다.
이는 대부분의 Java API에서 일반적이지 않습니다. 클래스 또는 인터페이스와 같은 일반적인 Java API에는 의미가 있으며, 그것이 나타내는 것에 대한 멘탈 모델을 개발하고이를 사용하여 작업을 이해할 수 있습니다. 고려 java.util.List
예를 들어. A List
는 다른 개체의 컨테이너입니다. 시퀀스와 인덱스가 있습니다. 목록에 포함 된 개체 수는에서 반환합니다 size()
. 각 개체에는 0..size-1 (포함) 범위의 인덱스가 있습니다. 인덱스 i에 있는 객체 는를 호출하여 검색 할 수 있습니다 list.get(i)
. 기타 등등.
의 기능적 인터페이스에는 java.util.function
그러한 의미가 없습니다. 대신 인수 수, 반환 값 수 및 (때로는) 인수 또는 반환 값이 원시인지 여부와 같은 함수 의 구조 를 단순히 나타내는 인터페이스입니다 . 따라서 우리는 TFunction<T,R>
유형의 단일 인수를 취하고 유형 R 값을 반환하는 함수를 나타내는 것과 같은 것이 있습니다 . 그게 다야. 그 기능은 무엇을합니까? 글쎄, 그것은 단일 인수를 취하고 단일 값을 반환하는 한 무엇이든 할 수 있습니다. 그래서 사양 이 "하나의 인수를 받아들이고 결과를 생성하는 함수를 나타냅니다."Function<T,R>
분명히 우리가 코드를 작성할 때 의미가 있고 그 의미는 어딘가에서 나와야합니다. 기능적 인터페이스의 경우 의미는 사용되는 컨텍스트에서 비롯됩니다. 인터페이스 Function<T,R>
는 분리 된 의미가 없습니다. 그러나 java.util.Map<K,V>
API에는 다음이 있습니다.
V computeIfAbsent(K key, Function<K,V> mappingFunction)
(간결성을 위해 와일드 카드를 생략)
아,이 사용은 Function
"매핑 기능"입니다. 그게 무엇을합니까? 이 컨텍스트에서이 key
맵에 아직없는 경우 매핑 함수가 호출되고 키가 전달되고 값을 생성 할 것으로 예상되며 결과 키-값 쌍이 맵에 삽입됩니다.
따라서 사양 Function
(또는 그 문제에 대한 다른 기능 인터페이스)을보고 그 의미를 식별하려고 할 수 없습니다. 그 의미를 이해하려면 다른 API에서 사용되는 위치를 살펴 봐야하며 그 의미는 해당 컨텍스트에만 적용됩니다.
A Supplier
는 인수를 취하지 않고 값을 반환하는 모든 메서드입니다. 그 역할은 말 그대로 예상되는 클래스의 인스턴스를 제공하는 것입니다. 예를 들어, 'getter'메소드에 대한 모든 참조는Supplier
public Integer getCount(){
return this.count;
}
인스턴스 메서드 참조 myClass::getCount
는의 인스턴스입니다 Supplier<Integer>
.
A Consumer
는 인수를 받고 아무것도 반환하지 않는 메서드입니다. 부작용으로 인해 호출됩니다. Java 용어로 a Consumer
는 void
메소드 의 관용구입니다 . '세터'방법이 좋은 예입니다.
public void setCount(int count){
this.count = count;
}
인스턴스 메서드 참조 myClass::setCount
는 Consumer<Integer>
및 의 인스턴스입니다 IntConsumer
.
A Function<A,B>
는 한 유형의 인수를 취하고 다른 유형을 리턴하는 모든 메소드입니다. 이를 '변환'이라고 할 수 있습니다. 는 Function<A,B>
을 소요 A
하고를 반환합니다 B
. 주목할만한 점은 주어진 값에 A
대해 함수가 항상 특정 값을 반환해야한다는 것입니다 B
. A
그리고 B
실제로 같은 다음과 같은 유형이 될 수 있습니다 :
public Integer addTwo(int i){
return i+2;
}
인스턴스 메서드 참조 myClass:addTwo
는 a Function<Integer, Integer>
및 ToIntFunction<Integer>
.
getter에 대한 클래스 메서드 참조는 함수의 또 다른 예입니다.
public Integer getCount(){
return this.count;
}
클래스 메서드 참조 MyClass::getCount
는 Function<MyClass,Integer>
및 의 인스턴스입니다 ToIntFunction<MyClass>
.
java.util.function 패키지에 소비자 / 공급자 / 기타 기능 인터페이스가 정의 된 이유 : 소비자와 공급자는 Java 8에서 제공되는 내장 기능 인터페이스 중 두 가지입니다. 이러한 내장 기능 인터페이스의 목적은 다음과 같습니다. 공통 기능 설명자 (기능적 메서드 서명 / 정의)를 갖는 기능적 인터페이스를위한 준비된 "템플릿"을 제공합니다.
우리는 우리가 통과한다면 다른 종류의 R.에 T 형으로 변환 할 필요가 말할 수 있는 방법에 매개 변수로 다음과 같이 정의 함수를 다음 방법은 그 기능 기능적 인터페이스를 정의 할 필요가 있음을 / 추상 메소드는 매개 변수를 유형 T를 입력으로하고 R 유형의 매개 변수를 출력으로 제공합니다. 이제 이와 같은 많은 시나리오가있을 수 있으며 프로그래머는 필요에 따라 여러 기능 인터페이스를 정의하게됩니다. 이러한 종류의 시나리오를 방지하고 프로그래밍을 쉽게하고 기능 인터페이스 사용에 대한 공통 표준을 가져 오기 위해 Predicate, Function, Consumer & Supplier와 같은 내장 기능 인터페이스 세트가 정의되었습니다.
소비자가하는 일 : 소비자 기능 인터페이스는 입력을 받아들이고 해당 입력으로 무언가를 수행하며 출력을 제공하지 않습니다. 정의는 다음과 같습니다 (Java 소스에서)-
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
여기서 accept ()는 입력을 받고 출력을 반환하지 않는 function \ abstract 메서드입니다. 따라서 Integer를 입력하려면 출력없이 무언가를 수행 한 다음 자체 인터페이스를 정의하는 대신 Consumer 인스턴스를 사용하십시오.
공급자는 무엇입니까 : 공급 기능 인터페이스는 입력을하지만 출력을 반환하지 않습니다. 다음과 같이 정의됩니다 (Java 소스에서)-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Integer와 같이 무언가를 반환하는 함수가 필요할 때마다 Supplier의 인스턴스를 사용하여 출력을 사용하지 않습니다.
소비자 및 공급 업체 인터페이스의 예제 사용과 함께 더 명확한 설명이 필요한 경우 동일한 내 블로그 게시물을 참조 할 수 있습니다. http://www.javabrahman.com/java-8/java-8-java-util- function-consumer-tutorial-with-examples / 및 http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
여기 에 내 질문에 대한 내 답변 과 여기 에 또 다른 답변을 참조하십시오. 간단히 말해서 이러한 새로운 인터페이스는 모든 사람이 사용할 수있는 규칙 과 설명 을 제공 합니다 (+ 다음과 같은 펑키 메서드 체인.forEach(someMethod().andThen(otherMethod()))
소비자 : 무언가를 취하고 무언가를하고 아무것도 반환하지 않습니다.void accept(T t)
공급자 : 아무것도 취하지 않고 무언가를 반환합니다 : T get()
(소비자의 역, 기본적으로 보편적 인 'getter'방법)
// Consumer: It takes something (a String) and does something (prints it)
List<Person> personList = getPersons();
personList.stream()
.map(Person::getName)
.forEach(System.out::println);
공급 업체 : 반복 코드 랩핑 (예 : 코드 실행 타이밍)
public class SupplierExample {
public static void main(String[] args) {
// Imagine a class Calculate with some methods
Double result1 = timeMe(Calculate::doHeavyComputation);
Double result2 = timeMe(Calculate::doMoreComputation);
}
private static Double timeMe(Supplier<Double> code) {
Instant start = Instant.now();
// Supplier method .get() just invokes whatever it is passed
Double result = code.get();
Instant end = Instant.now();
Duration elapsed = Duration.between(start,end);
System.out.println("Computation took:" + elapsed.toMillis());
return result;
}
}
Laymen 용어로,
공급자는 데이터를 제공하지만 데이터를 소비하지 않습니다. 프로그래밍 용어에서 인수를받지 않고 값을 반환하는 메서드입니다. 새 값을 생성하는 데 사용됩니다.
http://codedestine.com/java-8-supplier-interface/
소비자는 데이터를 소비하지만 데이터를 반환하지는 않습니다. 프로그래밍 용어에서 여러 인수를 사용하고 값을 반환하지 않는 메서드입니다.
소비자와 공급자는 자바에서 제공하는 인터페이스입니다. 소비자는 목록 요소를 반복하는 데 사용되며 공급자는 공급 개체의
코드 데모로 쉽게 이해할 수 있습니다.
소비자
package com.java.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* The Class ConsumerDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class ConsumerDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
List<String> str = new ArrayList<>();
str.add("DEMO");
str.add("DEMO2");
str.add("DEMO3");
/* Consumer is use for iterate over the List */
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String t) {
/* Print list element on consile */
System.out.println(t);
}
};
str.forEach(consumer);
}
}
공급자
package com.java.java8;
import java.util.function.Supplier;
/**
* The Class SupplierDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class SupplierDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
getValue(() -> "Output1");
getValue(() -> "OutPut2");
}
/**
* Gets the value.
*
* @param supplier
* the supplier
* @return the value
*/
public static void getValue(Supplier<?> supplier) {
System.out.println(supplier.get());
}
}
가장 간단한 대답은 다음과 같습니다.
소비자는 Function <T, Void>로 볼 수 있습니다. 공급 업체는 Function <Void, T>로 볼 수 있습니다.
Consumer
및Supplier
또한 검색 할 수 있습니다 자습서 를 들어Consumer
...