java - 在 Java 中将函数式接口声明为变量可能有哪些缺点?
问题描述
我已经在 Java 中尝试函数式编程一段时间了,并注意到我开始更喜欢使用包中的@FunctionalInterface
函数java.util.function
,例如 Functions、BiFunctions、UnaryOperators、Predicates、BiPredicates 等,而不是我的简单私有方法类。我知道他们的应用程序更推荐作为参数传递给另一个函数,这就是我通常倾向于使用它们的方式,但我现在只是发现它们立即并且更好。
事实上,我现在倾向于将其中一些声明为变量,然后在需要时在我的类中使用。
我似乎没有在任何地方找到关于使用这些而不是简单方法的指南或缺点。
那么:以这种方式使用它们有缺点吗?
- 一个例子:
为什么更喜欢:
private boolean foo(final int a, final int b){
return a < b;
}
代替:
private final BiPredicate<Integer,Integer> foo = (a,b) -> a < b;
我如何从我的最新项目中使用它们的一个例子:
private final BiFunction<BoardPosition, Pair<Integer, Integer>, BoardPosition> sumBoardPosWithPair = (pos,
pair) -> new BoardPositionImpl(pos.getX() + pair.getX(), pos.getY() + pair.getY());
private final Function<Pair<Integer, Integer>, UnaryOperator<BoardPosition>> unaryCreator = (
axis) -> (p) -> this.sumBoardPosWithPair.apply(p, axis);
/**
* If you need to call the fromFunction method twice for specular directions use
* this TriFunction specularNoLimitDirection instead.
*/
private final TriFunction<Piece, Vectors, Board, Set<BoardPosition>> specularNoLimitDirection = (piece, axis,
board) -> Stream.concat(
this.fromFunction(this.unaryCreator.apply(axis.getAxis()), piece, board,
board.getColumns() + board.getRows()).stream(),
this.fromFunction(this.unaryCreator.apply(axis.getOpposite()), piece, board,
board.getColumns() + board.getRows()).stream())
.collect(Collectors.toSet());
protected final Set<BoardPosition> fromFunction(final UnaryOperator<BoardPosition> function, final Piece piece,
final Board board, final int limit) {
/*
* The "function.apply" at the seed of the Stream.Iterate is used to skip the
* first element, that's itself, in fact a piece can't have as a possible move
* it's original position.
*/
final List<BoardPosition> positions = Stream.iterate(function.apply(piece.getPiecePosition()), function)
.takeWhile(board::contains)
.takeWhile(x -> board.getPieceAtPosition(x).isEmpty()
|| !board.getPieceAtPosition(x).get().getPlayer().equals(piece.getPlayer()))
.limit(limit).collect(Collectors.toList());
final Optional<BoardPosition> pos = positions.stream().filter(i -> board.getPieceAtPosition(i).isPresent()
&& !board.getPieceAtPosition(i).get().getPlayer().equals(piece.getPlayer())).findFirst();
/*
* The sublist excludes the last n-th element of the high-endpoint, for this
* reason we need to add 1.
*/
return pos.isEmpty() ? new HashSet<>(positions)
: new HashSet<>(positions.subList(0, positions.indexOf(pos.get()) + SINGLE_INCREMENT));
}
解决方案
您应该做最易读和可维护的事情。如果将这些函数放在具有描述性名称的变量中感觉像是解决问题的一种可读且可维护的方法,那很好。这样的编程没有错。
您可能还喜欢的中间立场是将逻辑放在普通的静态方法中:
private boolean foo(final int a, final int b){
return a < b;
}
然后在需要时使用方法引用来引用它:MyClass::foo
. 这在行为上等同于您定义的 lambda。
有很多方法可以编写此代码。每个人都对“正确”的做法有意见,但实际上有很多“正确”的方法。(还有一些不太正确的方法。)
推荐阅读
- mysql - 为什么从共享锁切换到排他锁会导致死锁并回滚所有其他阻塞的事务?
- web-scraping - Investment.com 的 Xpath 用于抓取
- powershell - 如何在不破坏 Param 的情况下定义用于 Powershell 中的 Param 定义的类?
- python - 使用ffmpeg制作视频时如何指定开始和结束帧
- ansible - 以其他用户身份运行 playbook
- node.js - TypeError:dbConn.GetInstance 不是函数
- mysql - MySQL Join 查询与组的执行时间过长
- python - 我无法使用 requests + BeautifulSoup 自动登录到 pastebin
- c++ - 在 .pcap 文件仍在被写入时读取它
- python - 使用异常捕获器中断 Python 块