我正在使用lambda表达式进行一些测试,但我的代码不能编译.我的lambda实现是错误的还是异常处理?以下代码的正确实现是什么?
class MyObject { }
interface Creatable<T> {
T create() throws IOException;
}
/* Using the code: */
Creatable<MyObject> creator = () -> {
try {
return new MyObject();
} catch (IOException e) {
e.printStackTrace();
}
};
MyObject obj1 = creator.create();
Run Code Online (Sandbox Code Playgroud)
如果我删除try catch块并声明抛出该方法的异常,代码将编译并正常运行.
Creatable<MyObject> creator = () -> new MyObject();
Run Code Online (Sandbox Code Playgroud)
编译错误是:
incompatible types: bad return type in lambda expression
我有两种方法:
class C1
{
void m1() {//does sth}
void m2(int x1, int x2) {//does sth}
}
Run Code Online (Sandbox Code Playgroud)
//记录任何方法所用的时间
logMethodExecTime(m1);
logMethodExecTime(m2);
Run Code Online (Sandbox Code Playgroud)
不知道如何使用JDK8功能接口和方法引用来定义方法'logMethodExecTime'的正确语法?
以下不起作用:
class Utils
{
public static void logMethodExecTime(Supplier<Void> s)
{
long start = System.nanoTime();
s.get();
long end = System.nanoTime();
System.out.println(((end-start)/1000000000d) + " secs");
}
}
Run Code Online (Sandbox Code Playgroud)
和调用:
C1 c = new C1();
Utils.logMethodExecTime(c::m1);
//Also how can we have one single definition of 'logMethodExecTime'
//to accept any method with any number of args
Utils.logMethodExecTime(c::m2);
Run Code Online (Sandbox Code Playgroud) 是否有可能以某种方式参数化 Java 8 Consumer?我想要有可重用的消费者,我可以在其中放置额外的参数。
List<DateTime> dates = new ArrayList<DateTime>();
Set<Alarm> alarms = new HashSet<Alarm>();
Consumer<Entry> entryConsumer1 = entry -> {
LocalTime time = entry.getDate().toLocalTime();
Alarm alarm = new Alarm(time, calendar1.getPattern());
alarms.add(alarm);
dates.add(entry.getDate());
};
Consumer<Entry> entryConsumer2 = entry -> {
LocalTime time = entry.getDate().toLocalTime();
Alarm alarm = new Alarm(time, calendar2.getPattern());
alarms.add(alarm);
dates.add(entry.getDate());
};
calendar1.generateEntries(criteria).forEach(entryConsumer1);
calendar2.generateEntries(criteria).forEach(entryConsumer2);
Run Code Online (Sandbox Code Playgroud)
calendar1, calendar2 是同一种类型
如您所见,两个消费者仅在一个论点上有所不同。是否可以简化此代码/不要重复?
我正在玩a的用法FunctionalInterface.我到处都看到了以下代码的多种变体:
int i = str != null ? Integer.parseInt() : null;
Run Code Online (Sandbox Code Playgroud)
我正在寻找以下行为:
int i = Optional.of(str).ifPresent(Integer::parseInt);
Run Code Online (Sandbox Code Playgroud)
但ifPresent只接受一个Supplier,Optional不能扩展.
我创建了以下内容FunctionalInterface:
@FunctionalInterface
interface Do<A, B> {
default B ifNotNull(A a) {
return Optional.of(a).isPresent() ? perform(a) : null;
}
B perform(A a);
}
Run Code Online (Sandbox Code Playgroud)
这允许我这样做:
Integer i = ((Do<String, Integer>) Integer::parseInt).ifNotNull(str);
Run Code Online (Sandbox Code Playgroud)
可以添加更多默认方法来执行诸如此类操作
LocalDateTime date = (Do<String, LocalDateTime> MyDateUtils::toDate).ifValidDate(dateStr);
Run Code Online (Sandbox Code Playgroud)
它读得很好Do [my function] and return [function return value] if [my condition] holds true for [my input], …
public class ArraysDemo {
public static void main(String[] args) {
int[] a = {0, 2, 4, 6, 8};
int[] b = {10, 12, 14, 16, 18};
Arrays.setAll(a, i -> b[i]+1);
System.out.println(Arrays.toString(a));
}
}
Run Code Online (Sandbox Code Playgroud)
输出: [11, 13, 15, 17, 19]
setAll()使用的函数的来源如下:
public static void setAll(int[] array, IntUnaryOperator generator) {
Objects.requireNonNull(generator);
for (int i = 0; i < array.length; i++)
array[i] = generator.applyAsInt(i);
}
Run Code Online (Sandbox Code Playgroud)
IntUnaryOperator 是一个功能界面,这是其来源的一部分:
public interface IntUnaryOperator {
int applyAsInt(int operand);
// rest methods are omitted
}
Run Code Online (Sandbox Code Playgroud)
如果我错了,请纠正我,但我对Java中lambda表达式的理解是,当我将lambda表达式作为参数传递给setAll() …
首先,请耐心等待.大部分时间我在Scala(有时只在JVM端)或其他语言工作,所以我的Java(8)知识有点受限!
我必须重构的代码充满了空检查.我想让一些pojo的属性设置/覆盖更好一点,并且很高兴能够使用Java 8来完成工作.
所以我创造了这个:
private <T> void setOnlyIfNotNull(final T newValue, Consumer<T> setter) {
if(newValue != null) {
setter.accept(newValue);
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
setOnlyIfNotNull(newUserName, user::setName);
Run Code Online (Sandbox Code Playgroud)
junit4-test看起来像这样:
@Test
public void userName_isOnlyUpdated_ifProvided() {
User user = new User("oldUserName");
UserUpdateRequest request = new UserUpdateRequest().withUserName("newUserName");
service.updateUser(user, request); // This calls setOnlyIfNotNull behind the curtain. And it does invoke the setter ONLY once!
assertThat(user.getUserName()).isEqualTo("newUserName");
}
Run Code Online (Sandbox Code Playgroud)
这很有效.在我请同事进行代码审查之前,我对自己很满意.在解释我做了什么之后,他详细说明了他认为这不起作用,因为函数仍然没有Java中的一等公民,而User-pojo没有扩展FunctionalInterface.接口也是在类级别而不是功能级别上提供的.
现在我想知道,为什么测试工作,我在这里滥用了什么?天真我只是想象Java编译器知道setter的T setT(T value)签名与a相同Consumer<T>.
编辑:详细说明一下:如果我将测试更改为失败,例如,assertThat(user.getUserName()).isEqualTo("Something");如果失败,则会按预期进行compareFailure!
我已经经历了许多具有相同标题的问题,但我没有得到我正在寻找的答案.
在Greeter下面的课程中有一个简单的sysout.据我了解,lambda关心的是签名(即返回类型和参数数量).但如果我删除
int add(int a);
它完美有效,因为编译器将检查Greeting接口中是否有任何可用的方法没有参数且返回类型为void.
但是当我在那里保留那个方法时,我得到了主题行中提到的编译错误,根据我的理解编译器将转到Greeting接口,它将看到有两种方法.但是应该没有歧义,因为我的lambda表达式查找返回类型为void且只有一个参数的方法.基于这个类比,只有一种方法,所以理想情况下它不应该给出错误.
我知道我的比喻在这里是错误的,我知道它必须是一个功能界面,但我也认为我上面提到的过程正是编译器的工作方式.
任何人都可以让我知道我错在哪里以及编译器在我的例子中是如何工作的?
问候界面
package lambadas;
public interface Greeting {
void perform();
int add(int a);
}
Run Code Online (Sandbox Code Playgroud)
迎宾班
package lambadas;
public class Greeter {
public static void main(String[] args) {
Greeting l = () -> System.out.println("hello");
l.perform();
}
}
Run Code Online (Sandbox Code Playgroud)
HelloWorldGreeting
package lambadas;
public class HelloWorldGreeting implements Greeting {
@Override
public void perform() {
System.out.println("hello world.!");
}
@Override
public int add(int a) {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud) 在前面的问题中,我曾问过我应该使用哪个FunctionalInterface?
现在,我尝试添加到List<Integer>而不是两个Integers a和b,这样每个索引都添加到另一个列表的相同索引中。
我以前有
BinaryOperator<Integer> binaryOperator = Integer::sum;
Run Code Online (Sandbox Code Playgroud)
用于使用加上两个整数binaryOperator.apply(int a,int b)。有没有类似的方式
BinaryOperator<List<Integer>> binaryOperator = List<Integer>::sum;
Run Code Online (Sandbox Code Playgroud)
然后得到结果List<Integer> cList?
我有枚举类的值,假设它会随着时间的推移而增长,我希望添加新枚举值的用户也能在某处提供强制作用.但是我不确定如何强迫他们提供实施,因为在其他课程中会有必要.例如
public enum DayType {
SUNDAY,
MONDAY;
}
Run Code Online (Sandbox Code Playgroud)
在课堂上提到
class X{
DateType dateType;
..
}
Run Code Online (Sandbox Code Playgroud)
并用于其他一些课程
if (x.getDateType().equals(DayType.SUNDAY)) {
...
}else if(x.getDateType().equals(DayType.MONDAY)){
..
}
Run Code Online (Sandbox Code Playgroud)
因此,如果有人添加了DateType,那么他应该被迫在上面的if-else逻辑中添加必要条件.如果可能,最好通过添加功能接口?
我无法在枚举类中强制执行,因为必需具有spring依赖性.
为什么将一个参数的方法引用作为期望类型的参数(BiConsumer抽象方法需要两个参数)传递是合法的?
例:
class Experiment {
private String name;
public Experiment(String name) {
this.name = name;
}
public void oneParamMethod(Object o) {
System.out.println(this.name + " and " + o);
}
public <T, S> void executeBiConsumer(BiConsumer<T, S> biCon, T in1, S in2) {
biCon.accept(in1, in2);
}
public static void main(String[] args) {
// notice that the name is "INSTANCE", but it won't be printed out
Experiment exp = new Experiment("INSTANCE");
// executeBiConsumer expects a functional of two params but is …Run Code Online (Sandbox Code Playgroud)