Java LinkedList迭代器卡顿:无法遍历列表及前进后退方法失效
问题:LinkedList迭代器遍历异常,前进/后退功能失效
我开发的Java程序采用LinkedList存储PlacesToVisit对象,按距离升序排列后,无法遍历完整的城镇列表,迭代器卡在索引1的位置。尝试调用previous()和next()方法移动游标,但前进(moveForward)和后退(moveBack)方法均无法正常执行,其中后退方法完全没有响应。
原始代码
Main类
import java.util.LinkedList; import java.util.Scanner; public class Main { public static void main(String[] args) { var places = new LinkedList<PlacesToVisit>(); addPlaces(places, new PlacesToVisit("Adelaide", 1374)); addPlaces(places, new PlacesToVisit("Brisbane", 917)); addPlaces(places, new PlacesToVisit("Perth", 3923)); addPlaces(places, new PlacesToVisit("Alice Springs", 2771)); addPlaces(places, new PlacesToVisit("Darwin", 3723)); addPlaces(places, new PlacesToVisit("Melbourne", 877)); addPlaces(places, new PlacesToVisit("Sydney", 0)); System.out.println("First place to go is " + places.getFirst()); boolean flag = true; while (flag) { Scanner sc = new Scanner(System.in); chooseOptions(); switch (sc.next().toUpperCase().substring(0, 1)) { case "M" -> printMenu(places); case "F" -> moveForward(places); case "B" -> moveBack(places); case "L" -> System.out.println(places); case "Q" -> flag = false; } } } private static void chooseOptions() { String options = (""" Available actions (Select word or letter) (F)orward (B)acward (M)enu (L)ist places (Q)uit"""); System.out.println(options + " "); } private static void printMenu(LinkedList<PlacesToVisit> list) { System.out.println(list); } private static void moveForward(LinkedList<PlacesToVisit> list) { var iterator = list.listIterator(); if (iterator.hasNext()) { iterator.next(); if (iterator.hasNext()) { System.out.println(iterator.next()); } } } private static void moveBack(LinkedList<PlacesToVisit> list) { var iterator = list.listIterator(); if (iterator.hasPrevious()) { iterator.previous(); if (iterator.hasPrevious()) { System.out.println(iterator.previous()); } } } private static void addPlaces(LinkedList<PlacesToVisit> list, PlacesToVisit place) { if (list.contains(place)) { System.out.println("Found duplicate " + place); return; } for (PlacesToVisit p : list) { if (p.getName().equalsIgnoreCase(place.getName())) { System.out.println("Duplicate found" + place); return; } } int matchIndex = 0; for (var listPlace : list) { if (place.getDistance() < listPlace.getDistance()) { list.add(matchIndex, place); return; } matchIndex++; } list.add(place); } }
PlacesToVisit类
public class PlacesToVisit { private String name; private int distance; public PlacesToVisit(String name, int distance) { this.name = name; this.distance = distance; } public String getName() { return name; } public int getDistance() { return distance; } @Override public String toString() { return String.format("%s distance = %d", name, distance); } }
问题根源与修复方案
核心问题
- 迭代器状态丢失:每次调用
moveForward/moveBack时,都会创建新的ListIterator,新迭代器初始位置永远在列表开头,导致前进每次只能走到第二个元素,后退时因初始位置无前置元素完全不执行。 - 移动逻辑错误:
moveForward连续调用两次next(),直接跳过元素;moveBack的前置判断逻辑完全无效。 - 重复元素判断失效:
PlacesToVisit未重写equals方法,list.contains(place)无法正确识别重复项。
修复后完整代码
Main类
import java.util.LinkedList; import java.util.Scanner; import java.util.ListIterator; public class Main { // 迭代器作为成员变量,保持游标状态 private static ListIterator<PlacesToVisit> iterator; public static void main(String[] args) { var places = new LinkedList<PlacesToVisit>(); addPlaces(places, new PlacesToVisit("Adelaide", 1374)); addPlaces(places, new PlacesToVisit("Brisbane", 917)); addPlaces(places, new PlacesToVisit("Perth", 3923)); addPlaces(places, new PlacesToVisit("Alice Springs", 2771)); addPlaces(places, new PlacesToVisit("Darwin", 3723)); addPlaces(places, new PlacesToVisit("Melbourne", 877)); addPlaces(places, new PlacesToVisit("Sydney", 0)); System.out.println("First place to go is " + places.getFirst()); // 初始化迭代器并定位到第一个元素 iterator = places.listIterator(); if (iterator.hasNext()) { iterator.next(); } boolean flag = true; Scanner sc = new Scanner(System.in); while (flag) { chooseOptions(); String input = sc.next().toUpperCase().substring(0, 1); switch (input) { case "M" -> printMenu(places); case "F" -> moveForward(); case "B" -> moveBack(); case "L" -> System.out.println(places); case "Q" -> flag = false; default -> System.out.println("无效输入,请重新选择"); } } sc.close(); } private static void chooseOptions() { String options = """ Available actions (Select word or letter) (F)orward (B)ackward (M)enu (L)ist places (Q)uit"""; System.out.println(options); } private static void printMenu(LinkedList<PlacesToVisit> list) { System.out.println(list); } private static void moveForward() { if (iterator.hasNext()) { System.out.println("当前位置:" + iterator.next()); } else { System.out.println("已到列表末尾,无法前进"); } } private static void moveBack() { if (iterator.hasPrevious()) { System.out.println("当前位置:" + iterator.previous()); } else { System.out.println("已到列表开头,无法后退"); } } private static void addPlaces(LinkedList<PlacesToVisit> list, PlacesToVisit place) { if (list.contains(place)) { System.out.println("发现重复项:" + place); return; } int matchIndex = 0; for (var listPlace : list) { if (place.getDistance() < listPlace.getDistance()) { list.add(matchIndex, place); return; } matchIndex++; } list.add(place); } }
PlacesToVisit类
public class PlacesToVisit { private String name; private int distance; public PlacesToVisit(String name, int distance) { this.name = name; this.distance = distance; } public String getName() { return name; } public int getDistance() { return distance; } @Override public String toString() { return String.format("%s distance = %d", name, distance); } // 重写equals,基于名称(忽略大小写)和距离判断重复 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PlacesToVisit that = (PlacesToVisit) o; return distance == that.distance && name.equalsIgnoreCase(that.name); } // 重写hashCode,与equals逻辑一致 @Override public int hashCode() { return name.toLowerCase().hashCode() + distance; } }
内容的提问来源于stack exchange,提问作者Felix Mbugua
相关产品推荐
相关产品推荐

