【发布时间】:2017-08-17 19:39:58
【问题描述】:
我有一个关于 Java 集合(例如 Set 或 List)的问题。更一般地,您可以在 for-each 循环中使用的对象。是否有任何要求它们的元素实际上必须存储在数据结构中的某个位置,或者它们只能从某种要求中描述并在需要时动态计算?感觉这应该是可以做到的,但我没有看到任何 java 标准集合类做这样的事情。我在这里违反了任何合同吗?
我正在考虑使用这些主要是数学。举例来说,我想要一个代表 1 000 000 以下的所有素数的集合。将它们保存在内存中可能不是一个好主意,而是有一个方法检查特定数字是否在集合中。
我也不是 java 流方面的专家,但我觉得这些应该可以在 java 8 流中使用,因为对象具有非常小的状态(集合中的对象甚至不存在,直到你尝试遍历它们或检查集合中是否存在特定对象)。
是否可以拥有具有几乎无限多元素的集合或迭代器,例如“6*k+1 形式的所有数字”、“10 以上的所有素数”或“此基础上的所有向量”?我正在考虑的另一件事是将两个集合组合起来,例如 1 000 000 以下的所有素数和 2^n-1 形式上的所有整数的并集,并列出 1 000 000 以下的梅森素数。我觉得这样会更容易如果以这种方式完成并且在实际需要元素之前没有显式创建元素,则对某些数学对象进行推理。也许我错了。
这是我写的两个模型类,试图说明我想要做什么。它们的行为并不完全符合我的预期(见输出),这让我觉得我在这里违反了可迭代接口的某种契约或错误地实现了它。如果您看到它,或者在集合框架下甚至允许这种代码,请随时指出我做错了什么。
import java.util.AbstractSet;
import java.util.Iterator;
public class PrimesBelow extends AbstractSet<Integer>{
int max;
int size;
public PrimesBelow(int max) {
this.max = max;
}
@Override
public Iterator<Integer> iterator() {
return new SetIterator<Integer>(this);
}
@Override
public int size() {
if(this.size == -1){
System.out.println("Calculating size");
size = calculateSize();
}else{
System.out.println("Accessing calculated size");
}
return size;
}
private int calculateSize() {
int c = 0;
for(Integer p: this)
c++;
return c;
}
public static void main(String[] args){
PrimesBelow primesBelow10 = new PrimesBelow(10);
for(int i: primesBelow10)
System.out.println(i);
System.out.println(primesBelow10);
}
}
.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SetIterator<T> implements Iterator<Integer> {
int max;
int current;
public SetIterator(PrimesBelow pb) {
this.max= pb.max;
current = 1;
}
@Override
public boolean hasNext() {
if(current < max) return true;
else return false;
}
@Override
public Integer next() {
while(hasNext()){
current++;
if(isPrime(current)){
System.out.println("returning "+current);
return current;
}
}
throw new NoSuchElementException();
}
private boolean isPrime(int a) {
if(a<2) return false;
for(int i = 2; i < a; i++) if((a%i)==0) return false;
return true;
}
}
Main function gives the output
returning 2
2
returning 3
3
returning 5
5
returning 7
7
Exception in thread "main" java.util.NoSuchElementException
at SetIterator.next(SetIterator.java:27)
at SetIterator.next(SetIterator.java:1)
at PrimesBelow.main(PrimesBelow.java:38)
edit:在 next() 方法中发现了一个错误。更正它并将输出更改为新的。
【问题讨论】:
-
我认为您不想为这些实现整个
Collection接口;你只想实现contains和iterator这样的成员方法,对吧? -
你知道
Iterable这个接口吗?它是 Collection 的超级,并且只包含iterator()函数。因为它甚至没有size()方法,也没有定义equals/hashCode 的契约,所以它非常适合延迟生成的无限序列。它可以在 for-each 循环中使用。 -
我的意思是,我绝对可以看到其他方法的用途,例如 addAll。我最感兴趣的事情是能够在一个不错的 for-each 循环中迭代无限的数据结构集,然后再实际创建任何对象,直到需要它们为止。
-
@user1661303 您的示例中的
hasNext()仍然与next()的实现不匹配-如果仅在达到max时返回false,但如果实际上存在素数则返回在到达max之前离开
标签: java collections iterator set