- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我今天正在试验这个问题,来自 Euler Problems:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
我考虑了一下,当然可以用 for 循环来完成,但是我想使用 Java 8,因为它打开了新的选项。
但是首先,我不知道如何生成 IntStream
产生这样的元素,所以我最终还是使用了普通的 for 循环:
public class Problem4 extends Problem<Integer> {
private final int digitsCount;
private int min;
private int max;
public Problem4(final int digitsCount) {
this.digitsCount = digitsCount;
}
@Override
public void run() {
List<Integer> list = new ArrayList<>();
min = (int)Math.pow(10, digitsCount - 1);
max = min * 10;
for (int i = min; i < max; i++) {
for (int j = min; j < max; j++) {
int sum = i * j;
if (isPalindrome(sum)) {
list.add(sum);
}
}
}
result = list.stream().mapToInt(i -> i).max().getAsInt();
}
private boolean isPalindrome(final int number) {
String numberString = String.valueOf(number);
String reversed = new StringBuilder(numberString).reverse().toString();
return (numberString.equals(reversed));
}
@Override
public String getName() {
return "Problem 4";
}
}
如您所见,我可能有点懒惰,真的有点 IntStream::max
是一个非常好的方法,我认为使用它比自己编写更好。
问题来了,我需要有一个list
现在能够以这种方式获得最大值,这意味着我需要存储数据,而我确实不应该这样做。
那么,现在的问题是,是否有可能在 Java 8 中实现它?
for (int i = min; i < max; i++) {
for (int j = min; j < max; j++) {
yield i * j;
}
}
然后用那个方法创建一个 PrimitiveIterator.OfInt
(拆箱版本的 Iterator<Integer>
,还是直接创建一个 IntStream
?
然后用 streamFromYield.filter(this::isPalindrome).max().getAsInt()
得到答案将非常容易实现。
最后,我知道以前有人问过这个问题,但是上次已经很久了,现在 Java 8 很快就会出现,他们在其中添加了一个大概念 Stream<T>
和新的语言结构,称为 lambdas。
因此,现在编写此类代码可能与人们为 Java 6 或 7 编写此类代码时截然不同。
最佳答案
好吧,我认为我们已经从“外部”使用 Streams API、使用 flatMap
、优化回文查找算法等。请参阅 Boris the Spider 的答案。和 assylias .然而,我们已经回避了最初的问题,即如何使用类似 Python 的 yield
语句来编写生成器函数。 (我认为 OP 的嵌套 - 例如 yield
使用的是 Python。)
使用 flatMap
的问题之一是并行拆分只能发生在最外层的流上。内部流(从 flatMap
返回)按顺序处理。我们可以尝试使内部流也平行,但它们可能会与外部流竞争。我想嵌套拆分可以工作,但我不太有信心。
一种方法是使用 Stream.generate
或(如 assylias 的回答)Stream.iterate
函数。但是,它们会创建无限流,因此必须提供外部 limit
来终止流。
如果我们可以创建一个有限但“扁平化”的流,以便整个值流都可以拆分,那就太好了。不幸的是,创建流并不像 Python 的生成器函数那样方便。不过,它可以毫不费力地完成。下面是一个使用 StreamSupport
和 AbstractSpliterator
类的示例:
class Generator extends Spliterators.AbstractIntSpliterator {
final int min;
final int max;
int i;
int j;
public Generator(int min, int max) {
super((max - min) * (max - min), 0);
this.min = min;
this.max = max;
i = min;
j = min;
}
public boolean tryAdvance(IntConsumer ic) {
if (i == max) {
return false;
}
ic.accept(i * j);
j++;
if (j == max) {
i++;
j = min;
}
return true;
}
}
public static void main(String[] args) {
Generator gen = new Generator(100, 1000);
System.out.println(
StreamSupport.intStream(gen, false)
.filter(i -> isPalindrome(i))
.max()
.getAsInt());
}
不是让迭代变量在堆栈上(就像在嵌套 for 和 yield 方法中那样)我们必须使它们成为对象的字段并让 tryAdvance
递增它们直到迭代完成完全的。现在,这是拆分器的最简单形式,不一定能很好地并行化。通过额外的工作,可以实现 trySplit
方法来进行更好的拆分,从而实现更好的并行性。
forEachRemaining
方法可以被覆盖,它看起来几乎像 nested-for-loop-with-yield 示例,调用 IntConsumer
而不是 产量
。不幸的是,tryAdvance
是抽象的,因此必须实现,因此仍然有必要将迭代变量作为对象的字段。
关于java - 是否有可能合理地模拟 yield-syntax,或许在 Java 8 的帮助下?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21972572/
我不知道为什么我得到这些结果。 ++ +add +syntax error 2 ++ +add +syntax error 4 ++是我的输入,并且lex会回显每个字符,并且每当获得+时yacc打印就
这个问题在这里已经有了答案: Syntax error on print with Python 3 [duplicate] (3 个回答) 关闭8年前。 为什么 Python 在第 9 行的简单 p
我有一个非常简单的 SQL 语句 SELECT * FROM Table; 但是,我的查询引擎返回一个语法错误。为什么? 错误详情: An unhandled exception of type 'S
我正在尝试编写一些代码来模拟具有两个三态缓冲器和VHDL中的上拉电阻的电路。下面是我的代码: library ieee; use ieee.std_logic_1164.all; entity Pul
我已经编写了这个mergesort实现,如果将除法功能放在mergesort函数之外,效果很好。但是,当我尝试使除法成为mergesort的内部函数时,遇到语法错误。 我知道,对此必须有一些非常简单的
(我是 Linux 和 Vim 新手,我正在尝试学习 Vim,但我遇到了一些无法解决的问题) 我安装的 Linux (Ubuntu 8.04) 无法使用 Vim 7.1.138 进行更新。 我的 vi
这个错误让我抓狂,我需要帮助。 Syntax Error: Token '{' invalid key at column 2 of the expression [{{ field }}.$erro
原标题是“特定于语言的配色方案防止较简单的配色方案为某些特定于语言的标签着色” 我正在使用 gVim 7.3(在 Ubuntu 12.04 Arch x86/64 上,这很重要)。 更新(2013-0
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
我正在编写某种“编译器”:它读取游戏的描述(包括房间,角色,事物等)。将其视为冒险类游戏的视觉版本,但存在很多简单问题。 当我运行“编译器”时,输入中出现语法错误,我不知道为什么。这是我的yacc输入
我正在构建一个示例应用程序(请参阅plunk https://plnkr.co/edit/vDXcSPrOjw5qvBQKcYvw?p=preview)。 var myA
语法错误文件: 我想知道在哪里可以看到确切的错误信息。vivado中没有任何提示。 谢谢! 最佳答案 通常,您可以检查屏幕底部的消息选项卡。无论如何,Vivado并不是特别擅长告诉您代码有什么问题(我
您好,这是我的迷你编程语言的野牛语法文件: %{ #include #include #include #include "projectbison.tab.h" void y
Fmax我的代码中的参数报告为:No Paths to report .因此,我试图使用 set_input_delay 设置与定义时钟的输入信号关系。 .但是,错误报告指出: Verilog HDL
我正在开发一个使用 Twig 的 Symfony2 项目,文件类型为 myfile.html.twig。 Vim 不会自动检测语法突出显示,因此不应用任何语法。打开文件后,我可以使用 :set syn
这是一个相对简单的代码,用于“在半径为2个单位的圆象限上使用中坐标规则评估pi”。 main.alg BEGIN REAL x, y, sumy, pi; INT n := lowerlimit, p
我对我的简单插入所产生的错误感到非常困惑。我已经通过不同的检查器多次检查了语法并搜索了类似的问题,但没有找到解决方案。 错误看起来像这样: 'SQLSTATE[42000]: Syntax error
我尝试了以下代码: with x as 1: y = 1 with z as 1: w = 1 编译器报告了 SyntaxError:语法无效。有什么问题? [已编辑:]我想做的是:
我在 Webstorm 中使用 vue 框架,使用 ES6 语法。 我已经安装了 vue-for-idea 插件,如果我使用纯 ES5 语法,一切都会很顺利。 但是代码的ES6部分似乎还没有被识别,并
我将我认为有用的代码示例作为文本文件保存在我的计算机上。我将它们存储为 txt 文件而不是编写它们的语言,以便它们将在 Notepad++ 中打开而不是在编辑器中打开(即我不希望我的 c++ 示例在
我是一名优秀的程序员,十分优秀!