英文:
How to check whether value is not present or just has no value?
问题
以下是翻译好的内容:
我对Java和Optional还不熟悉。在这里,我有一个未排序的质数数组。
List<Integer> primes = Arrays.asList(3, 7, 5, 2, 13, 11);
int getPrime()
{
primes.sort(); //使用Comparator
return (primes.stream()
.filter(prime -> prime > 15)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("没有这样的数字")));
}
情况A:我想返回第一个大于7的质数 - 运行良好。
情况B:我想返回第一个大于15的质数。
情况C:列表为空 / 由于某种原因,无法访问列表。
在情况B和C中,都会抛出相同的NoSuchElementException异常。在完全无法获取和能够获取但无法获得有效数字之间存在差异。
如何修改此代码,使其不会过于复杂,并检查这些情况呢?
英文:
I am new to Java and Optional. Here I have an unsorted array of primes.
List<Integer> primes = Arrays.asList(3, 7, 5, 2, 13, 11);
int getPrime()
{
primes.sort(); //using Comparator
return (primes.stream()
.filter(prime -> prime>15)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("No such number")));
}
Case A : I want to return the first prime number > 7 - works well.
Case B : I want to return the first prime number > 15
Case C : The list is empty / for some reason, it is not able to access list.
In case B & C ; the same NoSuchElementException is thrown. There is a difference between totally failing to fetch and being able to fetch but not get a valid number.
How can I change this code without it being too complicated such that these cases are checked?
答案1
得分: 0
你可以首先检查是否有任何元素,否则抛出异常,然后筛选流。
int getPrime() {
if (primes.isEmpty())
throw new NoSuchElementException("给定的列表为空。");
primes.sort(Comparator.naturalOrder());
return primes.stream()
.filter(prime -> prime > 15)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("找不到元素。"));
}
英文:
You could first check for any element and throw an exception otherwise and them filter the stream.
int getPrime() {
if (primes.isEmpty())
throw new NoSuchElementException("Empty list is given.")));
primes.sort(); //using Comparator
return (primes.stream()
.filter(prime -> prime > 15)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Element could not be found.")));
}
答案2
得分: 0
你可以尝试:
if(primes.size() == 0) throw new MyExcceptionForFailedToFetch();
但最好是在获取代码中抛出异常。
英文:
You can try
if(primes.size() == 0) throw new MyExcceptionForFailedToFetch();
But you better throw exception from fetching code.
答案3
得分: 0
我不同意你的陈述:
> 完全无法获取和能够获取但无法获得有效数字之间存在差异。
让我解释一下。
关于异常的准则是,方法内部行为应产生适当的返回值,而方法无法履行其合同的情况会导致异常。
那么,你的方法的“合同”是什么?你希望它搜索大于给定阈值的最小质数(至少,我是这样理解的)。我的推理是基于这个抽象。
从数学上讲,总会存在这样一个质数,因此该合同的理想实现将始终有一个答案。给定的实现有其局限性,因此存在无法履行其合同的情况。在这些情况下,抛出异常是正确的做法。
您列出了两种不同的失败情况,primes
列表为空(或无法访问 - 这已经是一种罕见的情况,已经抛出了自己的异常,因此我们可以忽略对于讨论的其余部分)与列表不包含大于您的阈值的质数。
对我来说,这种区别无关紧要。在这两种情况下,primes
列表对于所请求的阈值来说都太短了,元素为零只是“太短”的极端情况。在这两种情况下,返回值都是错误的,而应该抛出异常,以便调用者知道问题尚未得到答案。您已经在这样做。
调用者可能对失败原因感兴趣(大多数情况下,他只需要知道调用失败了,不关心为什么)。这在异常类型及其消息中得以表达。对于我的理解,NoSuchElementException
不是最能表达失败原因的选择。根据文档,“由各种访问方法抛出,表示请求的元素不存在。”在搜索大于给定阈值的最小质数的情境下,我可以想象应用该规范的两种不同解释:
- “元素”表示数学上的质数。正如我们所说,它肯定存在,因此我们会得出错误的陈述:“抛出…表示不存在下一个更高的质数。”
- “元素”表示质数列表中的元素。然后,该语句是正确的(“抛出…表示质数列表中适当的元素不存在”)。但对于调用者来说,这是无关紧要的,因为它涉及到一些调用者甚至不应该知道的实现细节:该方法在计算中使用了预定义的质数列表。
我更喜欢使用 UnsupportedOperationException
(文档 中说明为“抛出以指示不支持请求的操作。”,在我看来,这与失败完美地匹配。
因此,在您的代码中,我唯一会改变的是,抛出 new UnsupportedOperationException("primes list too short")
而不是 NoSuchElementException
。
英文:
I don't agree with your statement:
> There is a difference between totally failing to fetch and being able
> to fetch but not get a valid number.
Let me explain.
A guideline for exceptions is that behaviour within the contract of a method should produce appropriate return values, and cases where the method cannot fulfill its contract result in an exception.
So, what's the "contract" of your method? You want it to search for the smallest prime greater than a given threshold (at least, that's how I understand it). And my reasoning is based on that abstraction.
Mathematically, there will always exist such a prime number, so an ideal implementation of that contract would always have an answer. The given implementation has its limitations, so there are cases where it cannot fulfill its contract. In these cases, throwing an exception is the right thing to do.
You are listing two distinct cases of failure, the primes
list being empty (or inaccessible - a rare situation already throwing its own exception, so we can ignore that for the rest of the discussion) vs. the list not containing a prime bigger than your threshold.
Two me, this distinction doesn't matter. In both cases the primes
list is too short for the requested threshold, with zero elements just being an extreme case of "too short". In both cases, it would be wrong to return a value, instead, an exception should be thrown, so the caller knows the question hasn't been answered. You're already doing this.
The caller might be interested in the failure reason (most of the time, he just needs to know that the call failed and doesn't care why). That's expressed in the exception type plus its message. For my understanding, a NoSuchElementException
is not the choice that best expresses the failure reason. It's documented as "Thrown by various accessor methods to indicate that the element being requested does not exist." In the context of search for the smallest prime greater than a given threshold I can imagine two different interpretations of applying that specification:
- "element" to mean the mathematical prime. As we said, it surely exists, so we'd result in a false statement "Thrown ... to indicate that the next higher prime does not exist."
- "element" to mean the element in the list of prime numbers. Then the statement is correct ("Thrown ... to indicate that the appropriate element in the primes list does not exist"). But it's irrelevant to a caller, as it talks about some implementation detail that should the caller should not even know about: the fact that the method uses a predefined prime-numbers list in its computation.
I'd prefer an UnsupportedOperationException
(documented as "Thrown to indicate that the requested operation is not supported.", which in my opinion perfectly matches the failure.
So, the only thing I'd change in your code would be throwing a new UnsupportedOperationException("primes list too short")
instead of the NoSuchElementException
.
答案4
得分: -1
我希望这可以解决你的问题,而不使用流。
public static void main(String[] args) {
List<Integer> primes = Arrays.asList(3, 7, 5, 2, 13, 11);
if(!primes.isEmpty()) {
Collections.sort(primes);
for(int i : primes) {
if(i > 15) {
System.out.println(i);
break;
}
}
}else {
System.out.println("给定了空列表");
}
}
英文:
I hope this could fix your problem, without using streams.
public static void main(String[] args) {
List<Integer> primes = Arrays.asList(3, 7, 5, 2, 13, 11);
if(!primes.isEmpty()) {
Collections.sort(primes);
for(int i : primes) {
if(i > 15) {
System.out.println(i);
break;
}
}
}else {
System.out.println("Empty list is given");
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论