如何使用 Iterator java 获取前一个元素
How to get previous element with Iterator java
我有以下问题。我一直在做一个任务,其中给出了迭代器并且 Predicate class 必须检查迭代器中是否存在字符串。我覆盖了 Iterator 中的 hasNext()
和 next()
方法。他是 PredicateIteratorTest。我收到消息 junit.framework.AssertionFailedError: expected:<Java [and UML]> but was:<Java [11]> at PredicateIteratorTest.providesValuesBeginningWithJava(PredicateIteratorTest.java:37)
它应该 return 前一个元素。
public class PredicateIteratorTest {
private final List<String> values = List.of(//
"Java and UML", "UML and Java", "Java 11", "UML 2.0", "Effective Java");
private Iterator<String> valuesEndingWithJava;
private Iterator<String> valuesBeginningWithJava;
private Iterator<String> noValues;
@Before
public void setUp() {
valuesEndingWithJava = new PredicateIterator<>(values.iterator(), new EndsWith("Java"));
valuesBeginningWithJava = new PredicateIterator<>(values.iterator(), new StartsWith("Java"));
noValues = new PredicateIterator<>(values.iterator(), new StartsWith("Doesn't match"));
}
@Test
public void providesValuesEndingWithJava() {
assertTrue(valuesEndingWithJava.hasNext());
assertEquals("UML and Java", valuesEndingWithJava.next());
assertTrue(valuesEndingWithJava.hasNext());
assertEquals("Effective Java", valuesEndingWithJava.next());
}
}
这是 PredicateIterator class。在 if(predicate.test(iterator.next())){
之后,我想做一些与 ListIterator 中的方法 iterator.previous()
类似的事情,但不使用 ListIterator,因为测试只使用 Iterator。我怎样才能做到?
public class PredicateIterator<T> implements Iterator<T>{
private Iterator<T> iterator;
private Predicate<T> predicate;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate){
this.iterator = iter;
this.predicate = predicate;
}
@Override
public boolean hasNext(){
while(iterator.hasNext()){
if(predicate.test(iterator.next())){
return true;
}
}
return false;
}
@Override
public T next(){
T elem;
while (iterator.hasNext()){
elem = iterator.next();
if(predicate.test(elem)){
return elem;
}
}
throw new NoSuchElementException();
}
}
我通过添加 ListIterator 然后 iterator.previous() 更改了 PredicateIterator。但是现在我有测试错误 java.lang.UnsupportedOperationException at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73) at java.base/java.util.ImmutableCollections$ListItr.previous(ImmutableCollections.java:260) at PredicateIterator.hasNext(PredicateIterator.java:20) at PredicateIteratorTest.providesValuesBeginningWithJava(PredicateIteratorTest.java:36)
private ListIterator<T> iterator;
private Predicate<T> predicate;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate){
this.iterator = (ListIterator<T>) iter;
this.predicate = predicate;
}
@Override
public boolean hasNext(){
while(iterator.hasNext()){
if(predicate.test(iterator.next())){
iterator.previous();
return true;
}
}
return false;
}
好的,我找到问题了。我修改了你的 PredicateIterator<T>
class 以在进行谓词测试之前保存值。它似乎适用于定义的测试。
class PredicateIterator<T> implements Iterator<T> {
private Iterator<T> iterator;
private Predicate<T> predicate;
T value;
public PredicateIterator(Iterator<T> iter,
Predicate<T> predicate) {
this.iterator = iter;
this.predicate = predicate;
}
@Override
public boolean hasNext() {
while (iterator.hasNext()) {
value = iterator.next(); //<-- save value before test
if (predicate.test(value)) {
return true;
}
}
return false;
}
@Override
public T next() {
if (value != null) {
T retValue = value;
value = null;
return retValue; // <-- return saved value.
} else {
throw new NoSuchElementException();
}
}
}
再观察一次。如果您需要更改任何测试列表,您将无法更改,因为 List.of()
returns 是一个不可变的列表。但是您可以将其作为参数传递给可变实现。例如。 new ArrayList<>(List.of(...));
非常感谢,我复制了你的hasNext()
方法并修改了next()
,所以它看起来像这样:
@Override
public T next() {
if(value!= null){
if(predicate.test(value)) {
return value;
}
}
throw new NoSuchElementException();
}
第一次测试providesValuesEndingWithJava()
现在可以正确编译,但是现在出现了另一个问题。它抛出一个 NoSuchElementException
。这是测试和我收到的消息。我尝试使用 while(value!=null)
或 while(iterator.hasNext())
进行编译,但编译时间过长并崩溃。
@Test
public void hasNextReturnsFalseAfterLastElement1() {
valuesEndingWithJava.next();
valuesEndingWithJava.next();
assertFalse(valuesEndingWithJava.hasNext());
}
java.util.NoSuchElementException
at PredicateIterator.next(PredicateIterator.java:34)
at PredicateIteratorTest.hasNextReturnsFalseAfterLastElement1(PredicateIteratorTest.java:44)
创建一个布尔字段并将其分配给 false 但是它在 hasNext 方法中找到一个值后将其分配给 true 然后在 next 方法中检查此字段,如果它为 false 则意味着您之前调用了 next 方法hasNext方法,那么你必须在下一个方法中调用hasNext方法。
public class PredicateIterator<T> implements Iterator<T> {
private Predicate predicate;
private Iterator<T> iter;
private T type;
private boolean test = false;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate) {
if (iter == null || predicate == null) throw new NoSuchElementException();
this.predicate = predicate;
this.iter = iter;
}
@Override
public boolean hasNext() {
if (iter == null) throw new NoSuchElementException();
while (iter.hasNext()) {
type = iter.next();
if (predicate.test(type)) {
test = true;
return true;
}
}
return false;
}
@Override
public T next() {
if (!test) {
if ( hasNext()) {
T newTyp = type;
type = null;
test = false;
return newTyp;
}
}
else if (type != null) {
T newTyp = type;
type = null;
test = false;
return newTyp;
}
throw new NoSuchElementException();
}
}
我有以下问题。我一直在做一个任务,其中给出了迭代器并且 Predicate class 必须检查迭代器中是否存在字符串。我覆盖了 Iterator 中的 hasNext()
和 next()
方法。他是 PredicateIteratorTest。我收到消息 junit.framework.AssertionFailedError: expected:<Java [and UML]> but was:<Java [11]> at PredicateIteratorTest.providesValuesBeginningWithJava(PredicateIteratorTest.java:37)
它应该 return 前一个元素。
public class PredicateIteratorTest {
private final List<String> values = List.of(//
"Java and UML", "UML and Java", "Java 11", "UML 2.0", "Effective Java");
private Iterator<String> valuesEndingWithJava;
private Iterator<String> valuesBeginningWithJava;
private Iterator<String> noValues;
@Before
public void setUp() {
valuesEndingWithJava = new PredicateIterator<>(values.iterator(), new EndsWith("Java"));
valuesBeginningWithJava = new PredicateIterator<>(values.iterator(), new StartsWith("Java"));
noValues = new PredicateIterator<>(values.iterator(), new StartsWith("Doesn't match"));
}
@Test
public void providesValuesEndingWithJava() {
assertTrue(valuesEndingWithJava.hasNext());
assertEquals("UML and Java", valuesEndingWithJava.next());
assertTrue(valuesEndingWithJava.hasNext());
assertEquals("Effective Java", valuesEndingWithJava.next());
}
}
这是 PredicateIterator class。在 if(predicate.test(iterator.next())){
之后,我想做一些与 ListIterator 中的方法 iterator.previous()
类似的事情,但不使用 ListIterator,因为测试只使用 Iterator。我怎样才能做到?
public class PredicateIterator<T> implements Iterator<T>{
private Iterator<T> iterator;
private Predicate<T> predicate;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate){
this.iterator = iter;
this.predicate = predicate;
}
@Override
public boolean hasNext(){
while(iterator.hasNext()){
if(predicate.test(iterator.next())){
return true;
}
}
return false;
}
@Override
public T next(){
T elem;
while (iterator.hasNext()){
elem = iterator.next();
if(predicate.test(elem)){
return elem;
}
}
throw new NoSuchElementException();
}
}
我通过添加 ListIterator 然后 iterator.previous() 更改了 PredicateIterator。但是现在我有测试错误 java.lang.UnsupportedOperationException at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73) at java.base/java.util.ImmutableCollections$ListItr.previous(ImmutableCollections.java:260) at PredicateIterator.hasNext(PredicateIterator.java:20) at PredicateIteratorTest.providesValuesBeginningWithJava(PredicateIteratorTest.java:36)
private ListIterator<T> iterator;
private Predicate<T> predicate;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate){
this.iterator = (ListIterator<T>) iter;
this.predicate = predicate;
}
@Override
public boolean hasNext(){
while(iterator.hasNext()){
if(predicate.test(iterator.next())){
iterator.previous();
return true;
}
}
return false;
}
好的,我找到问题了。我修改了你的 PredicateIterator<T>
class 以在进行谓词测试之前保存值。它似乎适用于定义的测试。
class PredicateIterator<T> implements Iterator<T> {
private Iterator<T> iterator;
private Predicate<T> predicate;
T value;
public PredicateIterator(Iterator<T> iter,
Predicate<T> predicate) {
this.iterator = iter;
this.predicate = predicate;
}
@Override
public boolean hasNext() {
while (iterator.hasNext()) {
value = iterator.next(); //<-- save value before test
if (predicate.test(value)) {
return true;
}
}
return false;
}
@Override
public T next() {
if (value != null) {
T retValue = value;
value = null;
return retValue; // <-- return saved value.
} else {
throw new NoSuchElementException();
}
}
}
再观察一次。如果您需要更改任何测试列表,您将无法更改,因为 List.of()
returns 是一个不可变的列表。但是您可以将其作为参数传递给可变实现。例如。 new ArrayList<>(List.of(...));
非常感谢,我复制了你的hasNext()
方法并修改了next()
,所以它看起来像这样:
@Override
public T next() {
if(value!= null){
if(predicate.test(value)) {
return value;
}
}
throw new NoSuchElementException();
}
第一次测试providesValuesEndingWithJava()
现在可以正确编译,但是现在出现了另一个问题。它抛出一个 NoSuchElementException
。这是测试和我收到的消息。我尝试使用 while(value!=null)
或 while(iterator.hasNext())
进行编译,但编译时间过长并崩溃。
@Test
public void hasNextReturnsFalseAfterLastElement1() {
valuesEndingWithJava.next();
valuesEndingWithJava.next();
assertFalse(valuesEndingWithJava.hasNext());
}
java.util.NoSuchElementException
at PredicateIterator.next(PredicateIterator.java:34)
at PredicateIteratorTest.hasNextReturnsFalseAfterLastElement1(PredicateIteratorTest.java:44)
创建一个布尔字段并将其分配给 false 但是它在 hasNext 方法中找到一个值后将其分配给 true 然后在 next 方法中检查此字段,如果它为 false 则意味着您之前调用了 next 方法hasNext方法,那么你必须在下一个方法中调用hasNext方法。
public class PredicateIterator<T> implements Iterator<T> {
private Predicate predicate;
private Iterator<T> iter;
private T type;
private boolean test = false;
public PredicateIterator(Iterator<T> iter, Predicate<T> predicate) {
if (iter == null || predicate == null) throw new NoSuchElementException();
this.predicate = predicate;
this.iter = iter;
}
@Override
public boolean hasNext() {
if (iter == null) throw new NoSuchElementException();
while (iter.hasNext()) {
type = iter.next();
if (predicate.test(type)) {
test = true;
return true;
}
}
return false;
}
@Override
public T next() {
if (!test) {
if ( hasNext()) {
T newTyp = type;
type = null;
test = false;
return newTyp;
}
}
else if (type != null) {
T newTyp = type;
type = null;
test = false;
return newTyp;
}
throw new NoSuchElementException();
}
}