标签: method-reference

Java 8构造函数引用的可怕性能和大堆占用空间?

我刚刚在我们的生产环境中遇到了相当不愉快的经历 OutOfMemoryErrors: heapspace..

我将这个问题追溯到我ArrayList::new在函数中的使用.

要通过声明的构造函数(t -> new ArrayList<>())验证这实际上比正常创建更糟糕,我编写了以下小方法:

public class TestMain {
  public static void main(String[] args) {
    boolean newMethod = false;
    Map<Integer,List<Integer>> map = new HashMap<>();
    int index = 0;

    while(true){
      if (newMethod) {
        map.computeIfAbsent(index, ArrayList::new).add(index);
     } else {
        map.computeIfAbsent(index, i->new ArrayList<>()).add(index);
      }
      if (index++ % 100 == 0) {
        System.out.println("Reached index "+index);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

运行方法newMethod=true;将导致方法OutOfMemoryError在索引达到30k后失败.随着newMethod=false;程序不会失败,但一直冲击直到被杀(索引容易达到150万).

为什么在堆上ArrayList::new创建如此多的Object[]元素会导致OutOfMemoryError如此之快?

(顺便说一下 - 当集合类型出现时也会发生HashSet …

java constructor out-of-memory java-8 method-reference

107
推荐指数
2
解决办法
3570
查看次数

Comparator.reversed()不使用lambda进行编译

我有一个包含一些User对象的列表,我正在尝试对列表进行排序,但只能使用方法引用,使用lambda表达式,编译器会给出错误:

List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error
Run Code Online (Sandbox Code Playgroud)

错误:

com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
            userList.sort(Comparator.comparing(u -> u.getName()).reversed());
                                                     ^
symbol:   method getName()
location: variable u of type Object
1 error
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 method-reference

101
推荐指数
3
解决办法
2万
查看次数

方法参考缓存在Java 8中是个好主意吗?

考虑我有以下代码:

class Foo {

   Y func(X x) {...} 

   void doSomethingWithAFunc(Function<X,Y> f){...}

   void hotFunction(){
        doSomethingWithAFunc(this::func);
   }

}
Run Code Online (Sandbox Code Playgroud)

假设hotFunction经常被调用.那么缓存是否可取this::func,也许是这样的:

class Foo {
     Function<X,Y> f = this::func;
     ...
     void hotFunction(){
        doSomethingWithAFunc(f);
     }
}
Run Code Online (Sandbox Code Playgroud)

就我对java方法引用的理解而言,虚拟机在使用方法引用时会创建匿名类的对象.因此,缓存引用将仅创建该对象一次,而第一种方法在每个函数调用上创建它.它是否正确?

是否应缓存出现在代码中热位置的方法引用,或者VM是否能够对此进行优化并使缓存变得多余?是否存在关于此的一般最佳实践,或者这种高度VM实现是否特定于此类缓存是否有用?

java caching java-8 method-reference

72
推荐指数
3
解决办法
9230
查看次数

Java 8传递方法作为参数

目前正在进入Java 8 lambda表达式和方法引用.

我想传递一个没有args且没有返回值的方法作为另一个方法的参数.这就是我这样做的方式:

public void one() {
    System.out.println("one()");
}

public void pass() {
    run(this::one);
}

public void run(final Function function) {
    function.call();
}

@FunctionalInterface
interface Function {
    void call();
}
Run Code Online (Sandbox Code Playgroud)

我知道有一组预定义功能接口在java.util.function诸如Function<T,R>,但我没有找到一个不带任何参数,而不是产生结果.

java lambda java-8 method-reference

67
推荐指数
2
解决办法
8万
查看次数

Java 8数组构造函数引用如何工作?

假设我们有一个IntFunction返回整数数组的变量:

IntFunction<int[]> i;
Run Code Online (Sandbox Code Playgroud)

使用Java 8泛型,可以使用如下构造函数引用初始化此变量:

i = int[]::new
Run Code Online (Sandbox Code Playgroud)

Java编译器如何将其转换为字节码?

我知道对于其他类型,例如String::new,它可以使用invokedynamic指向String构造函数的指令java/lang/String.<init>(...),这只是一个具有特殊含义的方法.

这对数组有什么用处,看到有构造数组的特殊指令?

java arrays java-8 method-reference

44
推荐指数
1
解决办法
4574
查看次数

使用方法引用而不是lambda表达式抛出java.lang.NullPointerException

我注意到使用Java 8方法引用的未处理异常有些奇怪.这是我的代码,使用lambda表达式() -> s.toLowerCase():

public class Test {

    public static void main(String[] args) {
        testNPE(null);
    }

    private static void testNPE(String s) {
        Thread t = new Thread(() -> s.toLowerCase());
//        Thread t = new Thread(s::toLowerCase);
        t.setUncaughtExceptionHandler((t1, e) -> System.out.println("Exception!"));
        t.start();
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印"Exception",所以它工作正常.但是当我Thread t改为使用方法引用时(甚至IntelliJ建议):

Thread t = new Thread(s::toLowerCase);
Run Code Online (Sandbox Code Playgroud)

异常没有被捕获:

Exception in thread "main" java.lang.NullPointerException
    at Test.testNPE(Test.java:9)
    at Test.main(Test.java:4)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Run Code Online (Sandbox Code Playgroud)

有人能解释一下这里发生了什么吗?

java lambda nullpointerexception java-8 method-reference

44
推荐指数
2
解决办法
3597
查看次数

使用Java 8流时的新对象实例化

使用以下结构是否存在差异,除了后者的可读性稍好一些?

someList.stream().map(item -> new NewClass(item)).collect(Collectors.toList());

someList.stream().map(NewClass::new).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 java-stream method-reference

40
推荐指数
1
解决办法
5万
查看次数

为什么在编译时不检查lambda返回类型?

使用的方法引用具有返回类型Integer。但是String在下面的示例中,允许不兼容。

如何解决方法with声明以确保方法引用类型安全而无需手动强制转换?

import java.util.function.Function;

public class MinimalExample {
  static public class Builder<T> {
    final Class<T> clazz;

    Builder(Class<T> clazz) {
      this.clazz = clazz;
    }

    static <T> Builder<T> of(Class<T> clazz) {
      return new Builder<T>(clazz);
    }

    <R> Builder<T> with(Function<T, R> getter, R returnValue) {
      return null; //TODO
    }

  }

  static public interface MyInterface {
    Integer getLength();
  }

  public static void main(String[] args) {
// missing compiletimecheck is inaceptable:
    Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");

// compile time …
Run Code Online (Sandbox Code Playgroud)

java generics lambda type-inference method-reference

38
推荐指数
3
解决办法
1616
查看次数

使用带参数的方法引用

我刚开始学习Java流并遇到了问题.请看下面的例子.这是Node类的一部分:

private Map<String, Node> nodes;

public Optional<Node> child(String name) {
    return Optional.<Node>ofNullable(nodes.get(name));
}

private void findChildren(String name, List<Node> result) {
    child(name).ifPresent(result::add);
    nodes.values().stream()
//          .map(Node::findChildren(name, result))
//          .forEach(Node::findChildren(name, result))
            .forEach(node -> node.findChildren(name, result));
}
Run Code Online (Sandbox Code Playgroud)

我的目的是使用流中每个节点上的名称和结果参数调用#findChildren.我试图使用方法引用Node :: findChildren没有运气.我很欣赏其他与->运营商合作的解决方案.

是否有可能将方法引用与参数一起使用?我喜欢流的想法,我只想让代码更具可读性.

实际上,我认为有一个类似的问题方法引用与我读过的参数,但无法弄清楚如何在我的代码中使用bind2方法.这是唯一的解决方案吗?

java lambda java-stream functional-interface method-reference

35
推荐指数
1
解决办法
3万
查看次数

Java8方法引用用作Function对象来组合函数

Java8中是否有一种方法可以使用方法引用作为Function对象来使用其方法,例如:

Stream.of("ciao", "hola", "hello")
    .map(String::length.andThen(n -> n * 2))
Run Code Online (Sandbox Code Playgroud)

这个问题与之无关Stream,它只是作为例子使用,我想对方法参考有答案

java lambda java-8 method-reference

34
推荐指数
5
解决办法
7511
查看次数