我正在尝试定义一个方法,该方法接收字符串流,并返回一个排序列表,其中每个字符串都满足以下条件:
minLength
。even
。虽然我能够编译我的代码,但在运行它时我得到了
java.util.concurrent.TimeoutException
。
以下是我的方法:
public static List<String> findWinners(String pattern, int minLength, boolean even, Stream<String> stream) {
return stream
.filter(x -> x.matches(pattern) && x.length() >= minLength)
.filter(x -> x.length() % 2 == (even ? 0 : 1))
.sorted(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}).collect(Collectors.toList());
}
下面是完整的堆栈跟踪:
java.util.concurrent.TimeoutException
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)
at homeworkTests.StreamsHomeWorkTest.findWinners(StreamsHomeWorkTest.java:227)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:829)
根据您共享的堆栈跟踪,
TimeoutException
已从 get
的 FutureTask
方法中抛出。具体来说,接受超时的 overloaded 形式,因为没有参数的版本不会抛出 TimeoutException
。
在 java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)代码中的问题不在于流中,而在于传递给
get()
方法的超时,要么是因为值太小,要么是因为计算时间太长。一般来说,当不能保证时间上限时,建议使用不带参数的
get()
形式,因为该版本的方法会阻塞执行,直到完成或通过相应的异常中断。
Comparator
定义
Integer
。从 Java 8 开始,
Comparator
接口提供了方法
naturalOrder()
,该方法返回开箱即用的 Comparator
,以根据自然顺序比较
Comparable
元素。此外,通过减法定义元素之间的顺序很容易出错,因为操作可能会溢出。您的情况并非如此,因为您正在比较长度,因此值介于
0
和
Integer.MAX_VALUE
之间。但是,在定义比较逻辑时应该记住这一点。您的流可以像这样重写:
public static List<String> findWinners(String pattern, int minLength, boolean even, Stream<String> stream) {
return stream
.filter(x -> x.matches(pattern) && x.length() >= minLength && x.length() % 2 == (even ? 0 : 1))
.sorted(Comparator.naturalOrder())
.collect(Collectors.toList());
}