同时遍历两个列表



我正在尝试将下面的代码转换为Java 8(使用流(,但不确定如何使用流一起迭代两个列表。

public class ComparisonString {
private static List<String> input;
public static void main(String[] args) {
input = Arrays.asList("TRUE","FALSE","TRUE","N/A");
ComparisonString cs = new ComparisonString();
System.out.println(cs.getMatchedOutput(Arrays.asList("TRUE","N/A","N/A","FALSE")));
}
/**
* Check whether the 'input' List and the 'givenInput' List match.
* If a value is "N/A" in either lists then it means does-not-matter/don't-check-for-a-match-and-go-next
* @param givenInput
* @return
*/
public Optional<String> getMatchedOutput(final List<String> givenInput) {
boolean flag = true;
for (int i = 0; i < givenInput.size(); i++) {
if (this.input.get(i) != null
&& !(this.input.get(i).equalsIgnoreCase("N/A")
|| givenInput.get(i).equalsIgnoreCase("N/A"))
&& !this.input.get(i).equalsIgnoreCase(givenInput.get(i))) {
flag = false;
break;
}
}
if (flag) {
return Optional.of("flag = true");
} else {
return Optional.empty();
}
}
}

您的操作方式没有错,流对此做得太过火了,可能效率更低。然而,我要提出两个建议:

  • 不需要布尔值。在比较失败后立即使用return Optional.empty()。否则,在for循环之后为return Optional.of("flag = true")
  • 您应该检查List大小是否不等。如果您为循环选择较长的一个,它可能会引发异常。您可以取两个大小中的Math.min,忽略比较中的额外元素,或者只检查相等的列表大小,并决定这对应用程序的列表相等意味着什么

可以使用IntStream为两个列表生成索引流,然后过滤掉不相关的列表值并匹配其余值:

public Optional<String> getMatchedOutput(final List<String> givenInput) {
return IntStream.range(0, givenInput.size())
.filter(i -> null != input.get(i) && null != givenInput.get(i))
.filter(i -> !"N/A".equalsIgnoreCase(input.get(i)) && !"N/A".equalsIgnoreCase(givenInput.get(i)))
.allMatch(i -> input.get(i).equalsIgnoreCase(givenInput.get(i)))
? Optional.of("flag = true")
: Optional.empty();
}

测试已知数据:

input = Arrays.asList("TRUE","FALSE","TRUE","N/A");
ComparisonString cs = new ComparisonString();
System.out.println(cs.getMatchedOutput(Arrays.asList("TRUE","N/A","N/A","FALSE")));

打印:

Optional[flag = true]

您可以使用IntStream#noneMatch方法简化代码,如下所示:

private static List<String> input;
public static void main(String[] args) {
input = Arrays.asList("TRUE", "FALSE", "TRUE", "N/A");
System.out.println(
getMatchedOutput(Arrays.asList("TRUE", "N/A", "N/A", "FALSE")));
}
public static Optional<String> getMatchedOutput(final List<String> givenInput) {
return IntStream.range(0, givenInput.size()).noneMatch(i ->
input.get(i) != null
&& !(input.get(i).equalsIgnoreCase("N/A")
|| givenInput.get(i).equalsIgnoreCase("N/A"))
&& !input.get(i).equalsIgnoreCase(givenInput.get(i)))
? Optional.of("flag = true") : Optional.empty();
}

另请参阅:基于多个"可选"条件的过滤哈希映射

您可以使用另一种可能的解决方案。它看起来像pythonzip函数。

public class ComparisonString {
private static List<String> input;
public static void main(String[] args) {
input = Arrays.asList("TRUE", "FALSE", "TRUE", "N/A");
ComparisonString cs = new ComparisonString();
System.out.println(cs.getMatchedOutput(
Arrays.asList("TRUE", "N/A", "N/A", "FALSE")));
}
public Optional<String> getMatchedOutput(final List<String> givenInput) {
boolean notFlag = IntStream.range(0, input.size())
// zip to new object
.mapToObj(i -> new Pair<>(input.get(i), givenInput.get(i)))
// stop when the false flag is found
.anyMatch(p -> {
String inputValue = p.getKey();
String givenValue = p.getValue();
// true breaks the stream
return inputValue != null
&& !("N/A".equalsIgnoreCase(inputValue)
|| "N/A".equalsIgnoreCase(givenValue))
&& !inputValue.equalsIgnoreCase(givenValue);
});
if (!notFlag) {
return Optional.of("flag = true");
} else {
return Optional.empty();
}
}
}

输出

Optional[flag = true]

不幸的是,您不能使用流同时操作两个列表。您所能做的就是使用迭代器。我试着写了一些代码,它应该看起来像这样:

public static void streamTest(List<String> givenList) {
List<String> testing = new ArrayList<>();
IntStream.range(0, givenList.size())
.parallel()
.forEach(i -> {
if (input.get(i) != null
&& !(input.get(i).equalsIgnoreCase("N/A")
|| givenList.get(i).equalsIgnoreCase("N/A"))
&& !input.get(i).equalsIgnoreCase(givenList.get(i)))
testing.add("false");
});
if (testing.isEmpty())
System.out.println("flag = true");
else
System.out.println("flag = false");
}

我希望这能帮助你,给你一个开始。

最新更新