Java 理解迭代器
我正在做一个迭代器的练习,我有两个类“menu”和“dish”menu 班级菜单代表一个餐厅的菜肴集合。实现是在碟形的基本ArrayList上完成的。ArrayList迭代器用于迭代 我的疑问是,我是否可以在同一个类中使用不同的迭代器,以及如何使用 菜单类:Java 理解迭代器,java,oop,iteration,iterable,Java,Oop,Iteration,Iterable,我正在做一个迭代器的练习,我有两个类“menu”和“dish”menu 班级菜单代表一个餐厅的菜肴集合。实现是在碟形的基本ArrayList上完成的。ArrayList迭代器用于迭代 我的疑问是,我是否可以在同一个类中使用不同的迭代器,以及如何使用 菜单类: import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Menu implements Iterable<
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Menu implements Iterable<Plat> {
private List<Plat> plats=new ArrayList<Plat>();
@Override
public Iterator<Plat> iterator() {
return new IteratorVegetaria(plats);
}
public Iterator<Plat> iteratorCarnivoro() {
return new IteratorCarnivoro(plats);
}
public void afegirPlat(Plat p){
plats.add(p);
}
public static void main(String[] args) {
Menu m=new Menu();
Iterator<Plat> c=m.iteratorCarnivoro();
Iterator<Plat> v=m.iterator();
m.afegirPlat(new Plat("soup",1.5,true,false,true));
m.afegirPlat(new Plat("pizza",2.5,true,false,false));
m.afegirPlat(new Plat("chicken",5.80,false,true,true));
m.afegirPlat(new Plat("salad",2.5,true,false,true));
System.out.println("Non-vegetarian menu");
// Iteration without for-each
while (c.hasNext()){
System.out.println(c.next());
}
// Iteration with for-each (doesn't work and only show vegetarian dishes)
for(Plat p: m){
System.out.println(p);
}
System.out.println("Vegetarian menu:");
// Iteration without for-each
while(v.hasNext()){
System.out.println(v.next());
}
/* Iteration with for-each*/
for(Plat p: m){
System.out.println(p);
}
}
public class IteratorVegetaria implements Iterator<Plat>{
private List<Plat>plats;
private int actual=0;
public IteratorVegetaria(List<Plat>p){
plats = p;
}
// With this method we define that has next iterate as long as it finds an object that is vegetarian and adds it to the array.
@Override
public boolean hasNext() {
boolean hiHaNext = false;
int i = actual;
while (i<plats.size() && !hiHaNext){
if (plats.get(i).isVegetaria()) hiHaNext = true;
else i++;
}
return hiHaNext;
}
//With this method we define that next will iterate and jump to the next position when it finds a non-vegetarian dish
@Override
public Plat next() {
Plat p=plats.get(actual++);
while (!p.isVegetaria()){
p=plats.get(actual++);
}
return p;
}
}
public class IteratorCarnivoro implements Iterator<Plat>{
private List<Plat>plats;
private int actual=0;
public IteratorCarnivoro(List<Plat>p){
plats = p;
}
// With this method we define that has next iterate as long as it finds an object that is non-vegetarian and adds it to the array.
@Override
public boolean hasNext() {
boolean hiHaNext = false;
int i = actual;
while (i<plats.size() && !hiHaNext){
if (!plats.get(i).isVegetaria()) hiHaNext = true;
else i++;
}
return hiHaNext;
}
//With this method we define that next will iterate and jump to the next position when it finds a vegetarian dish
@Override
public Plat next() {
Plat p=plats.get(actual++);
while (p.isVegetaria()){
p=plats.get(actual++);
}
return p;
}
}
}
public class Plat {
private String nom;
private double preu;
private boolean vegetaria;
private boolean apteCeliacs;
private boolean baixCalories;
public Plat(String nom, double preu, boolean vegetaria, boolean apteCeliacs, boolean baixCalories) {
this.nom = nom;
this.preu = preu;
this.vegetaria = vegetaria;
this.apteCeliacs = apteCeliacs;
this.baixCalories = baixCalories;
}
public boolean isVegetaria() {
return vegetaria;
}
@Override
public String toString() {
String missatge = "Plat{" +
"nom='" + nom + '\'' +
", preu=" + preu +
", apteCeliacs=" + apteCeliacs +
", baixCalories=" + baixCalories +
", vegetaria=";
if (isVegetaria()){
return missatge+" es vegetaria";
}else{
return missatge+" no es vegetaria";
}
}
}
因此,基本上,当我运行代码时,它显示如下:
Non-vegetarian menu
Plat{nom='chicken', preu=5.8, apteCeliacs=true, baixCalories=true, vegetaria= no es vegetaria
Plat{nom='soup', preu=1.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
Plat{nom='pizza', preu=2.5, apteCeliacs=false, baixCalories=false, vegetaria= es vegetaria
Plat{nom='salad', preu=2.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
Vegetarian menu:
Plat{nom='soup', preu=1.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
Plat{nom='pizza', preu=2.5, apteCeliacs=false, baixCalories=false, vegetaria= es vegetaria
Plat{nom='salad', preu=2.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
Plat{nom='soup', preu=1.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
Plat{nom='pizza', preu=2.5, apteCeliacs=false, baixCalories=false, vegetaria= es vegetaria
Plat{nom='salad', preu=2.5, apteCeliacs=false, baixCalories=true, vegetaria= es vegetaria
这个while循环似乎被打破了。循环结构本身有点奇怪,很难阅读,但问题似乎是您似乎也从未更新
actual
while (i<plats.size() && !hiHaNext){
if (plats.get(i).isVegetaria()) hiHaNext = true;
else i++;
}
return hiHaNext;
虽然(如果这是一个学校案例研究,它成功地说明了如何为实现Iterable的类创建多个迭代器是一个坏主意:)我不是说这是不可能的,只是说这是不可取的
通常,如果要在使用进行迭代时更改集合,将使用迭代器
Iterator.remove();
如果您尝试在使用迭代器/ListIterator以外的任何东西循环遍历集合时删除元素,您将破坏我们都非常喜欢的ConcurrentModificationException
您应该利用Java8中引入的流(除非出于某种原因您使用的是旧版本)
列表菜单=新建ArrayList();
列表选项=menu.stream().filter(新谓词(){
@凌驾
公共布尔测试(图版){
返回板。isVegitarian();
}
}).collect(Collectors.toList());
列出非谓词选项=menu.stream().filter(新谓词(){
@凌驾
公共布尔测试(图版){
return!plate.isVegitarian();
}
}).collect(Collectors.toList());
在阅读代码时,像c
、m
和v
这样的变量名非常缺乏描述性,使代码更难阅读。考虑使用完整的单词和简短的短语,而不是单个字母。我改变了它,但是现在我运行代码时没有提示,在while循环中,我只是把变量“i”改为“实际”,谢谢让我知道!我明白了,所以我不应该使用迭代器,除非我想从集合中删除一些元素??我认为他们想让我们了解的是迭代器是如何在内部使用我们自己的,因为我们已经开始使用Java OOP及其方法和库,从Java 8+开始,我不建议在更新循环之外的任何地方使用迭代器,因为在更新循环中,需要减少集合,同时仍然循环。现在,您正在使用迭代器作为过滤器,这不是迭代器的用途。
Iterator.remove();
List<Plate> menu = new ArrayList();
List<Plate> vegetarianChoices = menu.stream().filter(new Predicate<Plate>() {
@Override
public boolean test(Plate plate) {
return plate.isVegitarian();
}
}).collect(Collectors.toList());
List<Plate> nonVegetarianChoices= menu.stream().filter(new Predicate<Plate>() {
@Override
public boolean test(Plate plate) {
return !plate.isVegitarian();
}
}).collect(Collectors.toList());