Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我们应该在什么时候使用Java8中的供应商?_Java_Java 8_Functional Interface - Fatal编程技术网

我们应该在什么时候使用Java8中的供应商?

我们应该在什么时候使用Java8中的供应商?,java,java-8,functional-interface,Java,Java 8,Functional Interface,这段代码之间有什么区别 Supplier<LocalDate> s1 = LocalDate::now; LocalDate s2 = LocalDate.now(); System.out.println(s1.get()); //2016-10-25 System.out.println(s2); //2016-10-25 suppliers1=LocalDate::now; localdates2=LocalDate.now(); System.out.println(s1

这段代码之间有什么区别

Supplier<LocalDate> s1 = LocalDate::now;
LocalDate s2 = LocalDate.now();

System.out.println(s1.get()); //2016-10-25
System.out.println(s2); //2016-10-25
suppliers1=LocalDate::now;
localdates2=LocalDate.now();
System.out.println(s1.get())//2016-10-25
系统输出打印LN(s2)//2016-10-25
我开始学习Java 8中的功能接口,不了解供应商的好处。确切地说,应该在何时以及如何使用它们。供应商是否在抽象级别上提高了性能或可能带来的好处

谢谢你的回答!这不是一个重复的问题,因为我使用了搜索,并没有找到我需要的东西

更新1: 你是说这个

    Supplier<Long> s1 = System::currentTimeMillis;
    Long s2 = System.currentTimeMillis();

    System.out.println(s1.get()); //1477411877817
    System.out.println(s2); //1477411877817
    try {
        Thread.sleep(3000l);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(s1.get()); //1477411880817 - different
    System.out.println(s2); //1477411877817
供应商s1=系统::currentTimeMillis;
Long s2=System.currentTimeMillis();
System.out.println(s1.get())//1477411877817
系统输出打印LN(s2)//1477411877817
试一试{
线程。睡眠(3000l);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(s1.get())//1477411880817-不同
系统输出打印LN(s2)//1477411877817

它肯定不会提高性能。你的问题类似于这个:为什么我们要使用变量?我们只需在每次需要时重新计算一切。对吧?

如果您需要多次使用某个方法,但它的语法冗长

假设您有一个名为
MyAmazingClass
的类,其中有一个名为
MyEventBetterMethod
的方法(它是静态的),您需要在代码中的15个不同位置调用它15次。当然,你可以做一些像

int myVar = MyAmazingClass.MyEvenBetterMethod();
// ...
int myOtherVar = MyAmazingClass.MyEvenBetterMethod();
// And so on...
……但你也可以这样做

Supplier<MyAmazingClass> shorter = MyAmazingClass::MyEvenBetterMethod;

int myVar = shorter.get();
// ...
int myOtherVar = shorter.get();
// And so on...
suppliershorter=MyAmazingClass::MyEventBetterMethod;
int myVar=shorter.get();
// ...
int myOtherVar=shorter.get();
//等等。。。

您混淆了函数接口和方法引用
Supplier
只是一个接口,类似于
Callable
,从Java 5开始您就应该知道这一点,唯一的区别是
Callable.call
允许抛出选中的
Exception
,与
Supplier.get
不同。因此,这些接口将具有类似的用例

现在,这些接口也恰好是功能接口,这意味着它们可以作为方法引用实现,指向调用接口方法时将调用的现有方法

所以在Java8之前,您必须编写

Future<Double> f=executorService.submit(new Callable<Double>() {
    public Double call() throws Exception {
        return calculatePI();
    }
});
/* do some other work */
Double result=f.get();

我将介绍一个场景,我们应该使用
Supplier
而不是
LocalDate

直接调用静态方法(如LocalDate.now())的代码很难进行单元测试。考虑一个场景,我们想测试一个方法:代码>代码()/>代码>计算一个人的年龄:

class Person {
    final String name;
    private final LocalDate dateOfBirth;

    Person(String name, LocalDate dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }

    long getAge() {
        return ChronoUnit.YEARS.between(dateOfBirth, LocalDate.now());
    }
}
这在生产中效果很好。但是,单元测试要么将系统的日期设置为已知值,要么每年更新一次,以期望返回的时间增加1,这两种解决方案都相当令人敬畏

更好的解决方案是单元测试注入已知日期,同时仍然允许生产代码使用
LocalDate.now()
。也许是这样的:

class Person {
    final String name;
    private final LocalDate dateOfBirth;
    private final LocalDate currentDate;

    // Used by regular production code
    Person(String name, LocalDate dateOfBirth) {
        this(name, dateOfBirth, LocalDate.now());
    }

    // Visible for test
    Person(String name, LocalDate dateOfBirth, LocalDate currentDate) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
        this.currentDate = currentDate;
    }

    long getAge() {
        return ChronoUnit.YEARS.between(dateOfBirth, currentDate);
    }

}
@Test
void testGetAge() {
    Supplier<LocalDate> injectedNow = ()-> LocalDate.parse("2016-12-01");
    Person person = new Person("John Doe", LocalDate.parse("2004-12-01"), injectedNow);
    assertEquals(12, person.getAge());
}
考虑这样一个场景:自对象创建以来,此人的生日已经过去。使用此实现,
getAge()
将基于创建Person对象的时间,而不是当前日期。我们可以通过使用
供应商
解决此问题:

import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Hello", "B2C", "World", "Stack Overflow", "is", "a", "gr8", "platform");

        Supplier<Stream<String>> streamSupplier = () -> list.stream()
                                                            .filter(s -> s.length() <= 5)
                                                            .map(s -> s.substring(1));

        System.out.println(streamSupplier.get().anyMatch(s -> Character.isLetter(s.charAt(0))));

        System.out.println(streamSupplier.get().anyMatch(s -> Character.isDigit(s.charAt(0))));
    }
}
我们的单元测试可以像这样注入“现在”日期:

class Person {
    final String name;
    private final LocalDate dateOfBirth;
    private final LocalDate currentDate;

    // Used by regular production code
    Person(String name, LocalDate dateOfBirth) {
        this(name, dateOfBirth, LocalDate.now());
    }

    // Visible for test
    Person(String name, LocalDate dateOfBirth, LocalDate currentDate) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
        this.currentDate = currentDate;
    }

    long getAge() {
        return ChronoUnit.YEARS.between(dateOfBirth, currentDate);
    }

}
@Test
void testGetAge() {
    Supplier<LocalDate> injectedNow = ()-> LocalDate.parse("2016-12-01");
    Person person = new Person("John Doe", LocalDate.parse("2004-12-01"), injectedNow);
    assertEquals(12, person.getAge());
}
@测试
void testGetAge(){
供应商injectedNow=()->LocalDate.parse(“2016-12-01”);
Person-Person=新人(“John Doe”,LocalDate.parse(“2004-12-01”),injectedNow);
assertEquals(12,person.getAge());
}

我确信您的问题已经得到了已经提供的答案的回答。这是我对供应商的理解


它为我提供了默认的Java定义接口,充当任何lambda方法ref目标返回时间的包装器。简单地说,只要您编写了一个没有参数并返回一个对象的方法,就可以由供应商接口包装。否则,在预泛型中,您将捕获返回作为对象类,然后强制转换,在泛型中,您将定义自己的T(ype)来保存返回值。它只是提供了一个统一的返回类型泛型holder,您可以在其上调用get()从上面提到的no arg方法中提取返回的对象。

第5项中的解释为我澄清了这一点:

Java8中引入的Supplier接口非常适合表示工厂。接受供应商输入的方法通常应使用有界通配符类型(项目31)约束工厂的类型参数,以允许客户机传入创建指定类型的任何子类型的工厂。例如,以下是一种使用客户提供的工厂制作马赛克的方法,以生产每个瓷砖:


Mosaic create(供应商我将添加我的观点,因为我对答案不满意:
当您想要延迟执行时,供应商很有用

无供应商

config.getLocalValue(getFromInternet() /*value if absent*/);
在调用getLocalValue之前,将调用getFromInternet,但只有在缺少本地值时才会使用getFromInternet()的值

现在,如果
config.getLocalValue
可以接受供应商,我们可以延迟此执行,并且如果存在本地值,我们将不会执行

config.getLocalValue(() -> getFromInternet())
差异
供应商使之成为可能:
仅在需要时执行

此示例说明了如何使用
供应商
提高绩效,但
供应商
本身不会提高绩效

/**
 * Checks that the specified object reference is not {@code null} and
 * throws a customized {@link NullPointerException} if it is.
 *
 * <p>Unlike the method {@link #requireNonNull(Object, String)},
 * this method allows creation of the message to be deferred until
 * after the null check is made. While this may confer a
 * performance advantage in the non-null case, when deciding to
 * call this method care should be taken that the costs of
 * creating the message supplier are less than the cost of just
 * creating the string message directly.
 *
 * @param obj     the object reference to check for nullity
 * @param messageSupplier supplier of the detail message to be
 * used in the event that a {@code NullPointerException} is thrown
 * @param <T> the type of the reference
 * @return {@code obj} if not {@code null}
 * @throws NullPointerException if {@code obj} is {@code null}
 * @since 1.8
 */
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
    if (obj == null)
        throw new NullPointerException(messageSupplier == null ?
                                       null : messageSupplier.get());
    return obj;
}
/**
*检查指定的对象引用是否不是{@code null}并且
*如果是,则抛出自定义的{@link NullPointerException}。
*
*与方法{@link#requirennull(Object,String)}不同,
*此方法允许将消息的创建延迟到
*在进行空检查之后。虽然这可能会导致
*表演广告
config.getLocalValue(() -> getFromInternet())
/**
 * Checks that the specified object reference is not {@code null} and
 * throws a customized {@link NullPointerException} if it is.
 *
 * <p>Unlike the method {@link #requireNonNull(Object, String)},
 * this method allows creation of the message to be deferred until
 * after the null check is made. While this may confer a
 * performance advantage in the non-null case, when deciding to
 * call this method care should be taken that the costs of
 * creating the message supplier are less than the cost of just
 * creating the string message directly.
 *
 * @param obj     the object reference to check for nullity
 * @param messageSupplier supplier of the detail message to be
 * used in the event that a {@code NullPointerException} is thrown
 * @param <T> the type of the reference
 * @return {@code obj} if not {@code null}
 * @throws NullPointerException if {@code obj} is {@code null}
 * @since 1.8
 */
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
    if (obj == null)
        throw new NullPointerException(messageSupplier == null ?
                                       null : messageSupplier.get());
    return obj;
}
import java.time.LocalDateTime;
import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        // Create a reference to the current date-time object when the following line is
        // executed
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);// Line-1

        // Create a reference to a functionality that will get the current date-time
        // whenever this functionality will be used
        Supplier<LocalDateTime> dateSupplier = LocalDateTime::now;

        // Sleep for 5 seconds
        Thread.sleep(5000);

        System.out.println(ldt);// Will display the same value as Line-1
        System.out.println(dateSupplier.get());// Will display the current date-time when this line will be executed

        // Sleep again for 5 seconds
        Thread.sleep(5000);

        System.out.println(ldt);// Will display the same value as Line-1
        System.out.println(dateSupplier.get());// Will display the current date-time when this line will be executed
    }
}
2021-04-11T00:04:06.205105
2021-04-11T00:04:06.205105
2021-04-11T00:04:11.211031
2021-04-11T00:04:06.205105
2021-04-11T00:04:16.211659
import java.util.List;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Hello", "B2C", "World", "Stack Overflow", "is", "a", "gr8", "platform");

        // A simple Stream for demo; you can think of a complex Stream with more
        // intermediate operations
        Stream<String> stream = list.stream()
                                    .filter(s -> s.length() <= 5)
                                    .map(s -> s.substring(1));

        System.out.println(stream.anyMatch(s -> Character.isLetter(s.charAt(0))));
        System.out.println(stream.anyMatch(s -> Character.isDigit(s.charAt(0))));
    }
}
true
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
    at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:528)
    at Main.main(Main.java:13)
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Hello", "B2C", "World", "Stack Overflow", "is", "a", "gr8", "platform");

        System.out.println(list.stream().filter(s -> s.length() <= 5).map(s -> s.substring(1))
                .anyMatch(s -> Character.isLetter(s.charAt(0))));
        
        System.out.println(list.stream().filter(s -> s.length() <= 5).map(s -> s.substring(1))
                .anyMatch(s -> Character.isDigit(s.charAt(0))));
    }
}
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<String> list = List.of("Hello", "B2C", "World", "Stack Overflow", "is", "a", "gr8", "platform");

        Supplier<Stream<String>> streamSupplier = () -> list.stream()
                                                            .filter(s -> s.length() <= 5)
                                                            .map(s -> s.substring(1));

        System.out.println(streamSupplier.get().anyMatch(s -> Character.isLetter(s.charAt(0))));

        System.out.println(streamSupplier.get().anyMatch(s -> Character.isDigit(s.charAt(0))));
    }
}
true
true