![](/img/trans.png)
[英]NoSuchElementException using Iterator class with HashSet
[英]Iterator for a Hashset class
我自己為我的元組 object 創建了一個 HashSet class。
我在為我的 TupleHashSet class 實現迭代器時遇到了麻煩。 hashArr 屬性存儲我的元組(對)對象的哈希集。 insert 方法根據計算的 HashCode 插入元組。
問題是如果我使用該方法插入某些內容,我的迭代器不會遍歷整個 HashArr。
我的老師告訴我一個提示,我的方法是錯誤的,因為 HashSet 值對順序不感興趣。 但是,我不確定他的意思。
元組哈希集
package pgdp.hashset;
import java.util.Iterator;
import java.util.NoSuchElementException;
import pgdp.pools.Tuple;
public class TupleHashSet<T, S> implements Iterable<Tuple<T, S>> {
private final Tuple<T, S>[] hashArr;
public static final int SIZE = 353;
public TupleHashSet() {
hashArr = new Tuple[SIZE];
}
@Override
public java.util.Iterator<Tuple<T, S>> iterator() {
return new Iterator(hashArr);
}
class Iterator implements java.util.Iterator<Tuple<T, S>> {
private Tuple<T, S>[] array;
private int index = 0;
Iterator(Tuple<T, S>[] t) {
this.array = t;
}
@Override
public boolean hasNext() {
for (int i = index; i < SIZE; ++i) {
if (array[i] != null) {
return true;
}
}
return false;
}
@Override
public Tuple<T, S> next() {
for (int i = index; i < SIZE; ++i) {
if (hashArr[i] != null) {
index = i + 1;
return hashArr[i];
}
}
throw new NoSuchElementException();
}
}
private int hash(Tuple<T, S> t, int i) {
return Math.abs((t.hashCode() + i) % SIZE);
}
public boolean insert(Tuple<T, S> t) {
int i = findPosition(t);
if (i == -1) {
return false;
}
hashArr[i] = t;
return true;
}
public Tuple<T, S> find(T t, S s) {
Tuple<T, S> testTuple = new Tuple<>(t, s);
return find(testTuple);
}
public Tuple<T, S> find(Tuple<T, S> t) {
int i = findPosition(t);
return i == -1 ? null : hashArr[i];
}
private int findPosition(Tuple<T, S> t) {
int i = 0;
int hash = hash(t, i);
int start = hash;
while (hashArr[hash] != null && !hashArr[hash].equals(t)) {
hash = hash(t, ++i);
if (hash == start) {
return -1;
}
}
return hash;
}
public boolean contains(Tuple<T, S> t) {
return find(t) != null;
}
public int insertedTuples() {
int res = 0;
for (Tuple<T, S> t : hashArr) {
if (t != null) {
res++;
}
}
return res;
}
public Tuple<T, S> removeFirstElement() {
Tuple<T, S> ret;
for (int i = 0; i < SIZE; i++) {
if (hashArr[i] != null) {
ret = hashArr[i];
hashArr[i] = null;
while (hashArr[(i + 1) % SIZE] != null) {
int c = 0;
int hash = hash(hashArr[(i + 1) % SIZE], c);
while (hashArr[hash] != null && hash != i + 1) {
hash = hash(hashArr[(i + 1) % SIZE], ++c);
}
if (hash != i + 1) {
hashArr[hash] = hashArr[(i + 1) % SIZE];
hashArr[(i + 1) % SIZE] = null;
}
i++;
}
return ret;
}
}
return null;
}
}
元組
package pgdp.pools;
import java.util.Objects;
public class Tuple<T, S> {
private T t;
private S s;
public Tuple(T t, S s) {
this.t = t;
this.s = s;
}
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other == null) {
return false;
}
if (this.getClass() != other.getClass()) {
return false;
}
Tuple<T, S> otherSub = (Tuple<T, S>) other;
return otherSub.s.equals(this.s) && otherSub.t.equals(this.t);
}
public int hashCode() {
return Objects.hash(t, s);
}
public T getT() {
return this.t;
}
public S getS() {
return this.s;
}
}
這個答案解決了您關於迭代器不返回所有項目的問題。
數組索引永遠不會增加,因此它總是會返回索引1
處的項目,即index + 1
。 index
在返回之前必須在對next
的調用中遞增,以便下一次調用從后備數組中的后續元素開始。
此外,后備數組並不密集(意味着在任意位置可能有空槽,這沒關系),所以next
function 必須找到下一個有效條目,而不是在下一個條目為空時放棄(即null
) .
試試這個:
@Override
public Iterator<Tuple<T, S>> iterator() {
Iterator<Tuple<T, S>> it = new Iterator<Tuple<T, S>>() {
private int index = 0;
@Override
public boolean hasNext() {
for (int i = index; i < SIZE; ++i) {
if (hashArr[i] != null) {
return true;
}
}
return false;
}
@Override
public Tuple<T, S> next() {
for (int i = index; i < SIZE; ++i)
if (hashArr[i] != null) {
index = i + 1;
return hashArr[i];
}
}
throw new NoSuchElementException();
}
};
return it;
}
這是一個可能的解決方案。
public boolean hasNext() {
for(; index < SIZE && hashArr[index] == null; index++);
return index < SIZE;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.