Question
Credit for work: This is what I have, but I keep getting errors: Exception in thread main java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(Unknown Source) at java.util.HashMap$KeyIterator.next(Unknown Source) at
Credit for work:
This is what I have, but I keep getting errors:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at airlines.FlightNet.removeAndDisconnect(FlightNet.java:42)
at airlines.AirGrader.checkFlightNet(AirGrader.java:258)
at airlines.AirGrader.main(AirGrader.java:301)
Airport.java
package airlines;
import java.util.*;
public class Airport implements Comparable
private String name;
private int x;
private int y;
private Set
public Airport(String name, int x, int y) {
this.name = name;
this.x = x;
this.y = y;
connections = new TreeSet<>();
}
public String getName() {
return name;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public List
return new ArrayList<>(connections);
}
// Adds that airport to the list of connections.
public void connectTo(Airport that) {
connections.add(that);
}
//
// Does nothing if this airport is not connected to that.
//
public void disconnectFrom(Airport that) {
if (!connections.contains(that))
return;
connections.remove(that);
}
// Use best practice.
public boolean equals(Object x) {
Airport that = (Airport) x;
return this.compareTo(that) == 0;
}
// Just compare by airport name.
public int compareTo(Airport that) {
int getCmp = this.getName().compareTo(that.getName());
return getCmp;
}
public boolean isConnectedTo(Airport that) {
if (connections.contains(that))
return true;
return false;
}
public String toString() {
return "Airport " + name + " @(" + x + "," + y + ")";
}
}
FlightNet.java
package airlines;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class FlightNet extends HashSet
public boolean nameIsAvailable(String name) {
for (Airport b : this) {
if (b.getName().equals(name)) {
return false;
}
}
return true;
}
public void connect(Airport a1, Airport a2) {
a1.connectTo(a2);
a2.connectTo(a1);
}
public void disconnect(Airport a1, Airport a2) {
a1.disconnectFrom(a2);
a2.disconnectFrom(a1);
}
public void removeAndDisconnect(Airport removeMe) {
for (Airport b : this) {
if (b.isConnectedTo(removeMe)) {
b.disconnectFrom(removeMe);
this.remove(removeMe);
}
}
}
public Airport getAirportNearXY(int x, int y, int maximumDistance) {
for (Airport b : this) {
double travelDistance = Math.hypot(x - b.getX(), y - b.getY());
if (travelDistance <= maximumDistance) {
return b;
}
}
return null;
}
}
RoutesPanel.java (dont need to edit)
package airlines;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
public class RoutesPanel extends JPanel
{
private final static Font FONT = new Font("SansSerif", Font.PLAIN, 12);
private final static int CLICK_RADIUS = 11;
private final static Color UNARMED_COLOR = Color.BLACK;
private final static Color ARMED_FOR_CONNECTION_COLOR = new Color(0, 200, 0);
private final static Color ARMED_FOR_DELETION_COLOR = Color.RED;
private final static File MAP_FILE = new File("pix/usmap.jpg");
private final static Color WHITEWASH_COLOR = new Color(255, 255, 255, 200);
private final static Stroke ROUTE_STROKE = new BasicStroke(2);
private FlightNet net;
private Airport armedAirport;
private BufferedImage usMapImage;
RoutesPanel()
{
try
{
usMapImage = ImageIO.read(MAP_FILE);
}
catch (IOException x)
{
sop("Can't read map image file " + MAP_FILE.getAbsolutePath());
System.exit(1);
}
net = new FlightNet();
setPreferredSize(new Dimension(usMapImage.getWidth()/2, usMapImage.getHeight()/2));
MLis lis = new MLis();
addMouseListener(lis);
addMouseMotionListener(lis);
}
private class MLis extends MouseAdapter
{
@Override
public void mouseClicked(MouseEvent e)
{
Airport clickedAirport = net.getAirportNearXY(e.getX(), e.getY(), CLICK_RADIUS);
// First of 1 or 2 clicks.
if (armedAirport == null)
{
if (clickedAirport == null)
{
// Click in empty space to create new airport.
armedAirport = null;
NameDia dia = new NameDia(e.getX(), e.getY());
dia.setVisible(true);
}
else
{
// Click on existing airport to arm it.
armedAirport = clickedAirport;
}
}
// Second of 2 clicks
else
{
if (clickedAirport == null)
{
// 2nd click in empty space to cancel operation.
armedAirport = null;
}
else if (clickedAirport == armedAirport)
{
// 2nd click on armed airport to delete it.
net.removeAndDisconnect(armedAirport);
armedAirport = null;
}
else if (clickedAirport.isConnectedTo(armedAirport))
{
// 2nd click on connected airport to delete the connection.
net.disconnect(armedAirport, clickedAirport);
armedAirport = null;
}
else
{
// 2nd click on unconnected airport to connect it.
net.connect(armedAirport, clickedAirport);
armedAirport = null;
}
}
repaint();
}
} // MLis
private class NameDia extends JDialog implements ActionListener
{
private int x;
private int y;
private JTextField tf;
private JButton okBtn;
private JButton cancelBtn;
NameDia(int x, int y)
{
this.x = x;
this.y = y;
JPanel pan = new JPanel();
pan.add(new JLabel("3-letter name: "));
tf = new JTextField(4);
tf.addActionListener(this);
pan.add(tf);
add(pan, BorderLayout.NORTH);
pan = new JPanel();
okBtn = new JButton("Ok");
okBtn.addActionListener(this);
pan.add(okBtn);
cancelBtn = new JButton("Cancel");
cancelBtn.addActionListener(this);
pan.add(cancelBtn);
add(pan, BorderLayout.SOUTH);
pack();
setModal(true);
}
@Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == cancelBtn)
{
setVisible(false);
}
else
{
String name = tf.getText().trim();
if (name.length() != 3)
{
JOptionPane.showMessageDialog(this, "Name must be 3 letters");
return;
}
if (!net.nameIsAvailable(name))
{
JOptionPane.showMessageDialog(this, "Name is in use");
return;
}
setVisible(false);
net.add(new Airport(name, x, y));
repaint();
}
}
} // NameDia
public void paintComponent(Graphics g)
{
// Background.
g.drawImage(usMapImage, 0, 0, getWidth(), getHeight(), this);
// Whitewash.
g.setColor(WHITEWASH_COLOR);
g.fillRect(0, 0, getWidth(), getHeight());
// Existing routes in black. If an airport is armed, some will get overdrawn.
g.setColor(UNARMED_COLOR);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(ROUTE_STROKE);
for (Airport a: net)
for (Airport dest: a.getConnections())
g.drawLine(a.getX(), a.getY(), dest.getX(), dest.getY());
// Routes that are armed for deletion.
if (armedAirport != null)
{
g.setColor(ARMED_FOR_DELETION_COLOR);
for (Airport dest: armedAirport.getConnections())
g.drawLine(armedAirport.getX(), armedAirport.getY(), dest.getX(), dest.getY());
}
// Routes that are armed for connection.
if (armedAirport != null)
{
g.setColor(ARMED_FOR_CONNECTION_COLOR);
for (Airport dest: net)
{
if (dest == armedAirport)
continue;
if (armedAirport.getConnections().contains(dest))
continue;
g.drawLine(armedAirport.getX(), armedAirport.getY(), dest.getX(), dest.getY());
}
}
// Airports
g.setFont(FONT);
for (Airport a: net)
if (a != armedAirport)
paintAirport(g, a);
if (armedAirport != null)
paintAirport(g, armedAirport);
}
private void paintAirport(Graphics g, Airport a)
{
int x = a.getX();
int y = a.getY();
boolean armed = a == armedAirport;
g.setColor(armed ? ARMED_FOR_DELETION_COLOR : UNARMED_COLOR);
g.fillOval(x-2, y-2, 5, 5);
g.drawOval(x-5, y-5, 11, 11);
int sw = g.getFontMetrics().stringWidth(a.getName());
g.drawString(a.getName(), x-sw/2, y+18);
}
static void sop(Object x) { System.out.println(x); }
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.add(new RoutesPanel());
frame.pack();
frame.setLocation(100, 100);
frame.setVisible(true);
}
}
AirGrader.java (dont need to edit)
package airlines;
import java.lang.reflect.*;
import java.util.*;
public class AirGrader
{
private final static Airport AAA = new Airport("AAA", 10, 20);
private final static Airport BBB1 = new Airport("BBB", 10, 20);
private final static Airport BBB2 = new Airport("BBB", 10, 20);
private final static Airport BBB3 = new Airport("BBB", 99, 88);
private final static Airport CCC = new Airport("CCC", 10, 20);
private final static Airport DDD = new Airport("DDD", 10, 20);
private final static Airport MMM = new Airport("MMM", 10, 20);
private final static Airport NNN = new Airport("NNN", 10, 20);
private static void checkAirport()
{
// Class.
Class> airportClass = null;
try
{
airportClass = Class.forName("airlines.Airport");
}
catch (ClassNotFoundException x)
{
abortZeroPoints("No airlines.Airport class");
}
// Implements Comparable
Class>[] interfaces = airportClass.getInterfaces();
boolean hasComparable = false;
for (Class> c: interfaces)
{
if (c.getName().equals("java.lang.Comparable"))
{
hasComparable = true;
break;
}
}
if (!hasComparable)
abortZeroPoints("Airport doesn't implement Comparable
// equals() calls compareTo()
SubAirport sub1 = new SubAirport("XXX", 0, 0);
SubAirport sub2 = new SubAirport("ZZZ", 0, 0);
sub1.equals(sub2);
if (!sub1.compareToWasCalled)
abortZeroPoints("In Airport, equals() doesn't call compareTo => Not best practice");
// equals()
checkEquals(AAA, BBB1, false);
checkEquals(BBB1, BBB2, true);
checkEquals(BBB1, BBB3, true);
// compareTo()
checkCompareTo(AAA, BBB1, -1);
checkCompareTo(BBB1, BBB2, 0);
checkCompareTo(BBB1, BBB3, 0);
// getConnections() should return sorted airports.
Airport that = new Airport("ZZZ", 1, 0);
Airport[] addOrder = { CCC, DDD, BBB1, AAA };
Airport[] expectOrder = { AAA, BBB1, CCC, DDD };
for (Airport a: addOrder)
that.connectTo(a);
List
String errPiece = "Added in this order:";
for (Airport a: addOrder)
errPiece += " " + a;
errPiece += " getConnections() returned:";
for (Airport a: conns)
errPiece += " " + a;
errPiece += " expected:";
for (Airport a: expectOrder)
errPiece += " " + a;
if (conns.size() != 4)
abortZeroPoints("Wrong number of airports: " + errPiece);
for (int i=0; i<4; i++)
if (!conns.get(i).equals(expectOrder[i]))
abortZeroPoints("getConnections returned airports in wrong order " + errPiece);
// isConnectedTo.
that = new Airport("XYZ", 0, 0);
that.connectTo(CCC);
that.connectTo(DDD);
Airport[] connOrder = { CCC, DDD };
Airport[] checks = { CCC, DDD, MMM, NNN };
boolean[] bExpect = { true, true, false, false };
for (Airport a: connOrder)
that.connectTo(a);
boolean trouble = false;
for (int i=0; i<4; i++)
if (that.isConnectedTo(checks[i]) != bExpect[i])
trouble = true;
if (trouble)
{
String err = "Connected an airport to " + CCC + " and " + DDD;
for (int i=0; i<4; i++)
err += " isConnectedTo(" + checks[i] + ") returned " + that.isConnectedTo(checks[i]) + ", expected " + bExpect[i];
abortZeroPoints(err);
}
}
private static void checkEquals(Airport a1, Airport a2, boolean expect)
{
boolean result = a1.equals(a2);
if (result != expect)
abortZeroPoints("equals() on " + a1 + " and " + a2 + " returned " + result + ", should be " + expect);
result = a2.equals(a1);
if (result != expect)
abortZeroPoints("equals() on " + a2 + " and " + a1 + " returned " + result + ", should be " + expect);
}
private static void checkCompareTo(Airport a1, Airport a2, int expectSignum)
{
int result = a1.compareTo(a2);
if (Math.signum(result) != expectSignum)
abortZeroPoints("compareTo() on " + a1 + " and " + a2 + " returned " + result + ", should be " + signumToString(expectSignum));
result = a2.compareTo(a1);
expectSignum *= -1;
if (Math.signum(result) != expectSignum)
abortZeroPoints("compareTo() on " + a2 + " and " + a1 + " returned " + result + ", should be " + signumToString(expectSignum));
}
private static String signumToString(int n)
{
if (n == 0)
return "0";
else if (n < 0)
return "<0";
else
return ">0";
}
private static class SubAirport extends Airport
{
boolean compareToWasCalled;
SubAirport(String name, int x, int y)
{
super(name, x, y);
}
public int compareTo(Airport that)
{
compareToWasCalled = true;
return 0;
}
}
private static void checkFlightNet()
{
// Extends HashSet?
Class fnClass = null;
try
{
fnClass = Class.forName("airlines.FlightNet");
}
catch (ClassNotFoundException x)
{
abortZeroPoints("No airlines.FlightNet class");
}
Class supeClass = fnClass.getSuperclass();
try
{
Class hsClass = Class.forName("java.util.HashSet");
if (hsClass != supeClass)
abortZeroPoints("FlightNet doesn't extend HashSet");
}
catch (ClassNotFoundException x) { } // Shouldn't happen, ignore if it does
// Add
FlightNet that = new FlightNet();
Airport[] adds = { AAA, BBB1, CCC, DDD };
String addsErr = "Added to a FlightNet:";
for (Airport a: adds)
{
that.add(a);
addsErr += " " + a;
}
// Name availability
for (Airport a: adds)
{
if (that.nameIsAvailable(a.getName()))
{
String err = addsErr + " Then nameIsAvailable(" + a.getName() + ") returned true";
abortZeroPoints(err);
}
}
if (!that.nameIsAvailable("SFO"))
{
String err = addsErr + " Then nameIsAvailable(\"SFO\") returned false";
abortZeroPoints(err);
}
// Connection
that = new FlightNet();
Airport sfo = new Airport("SFO", 0, 0);
Airport jfk = new Airport("JFK", 100, 100);
that.add(sfo);
that.add(jfk);
that.connect(sfo, jfk);
if (sfo.isConnectedTo(jfk) == false || jfk.isConnectedTo(sfo) == false)
{
String err = "Created a FlightNet fn, then fn.connect(sfo, jfk); ";
err += "Then sfo.isConnectedTo(jfk) returned " + sfo.isConnectedTo(jfk) + " and ";
err += "jfk.isConnectedTo(sfo) returned " + jfk.isConnectedTo(sfo) + " Both should return true";
abortZeroPoints(err);
}
Airport sea = new Airport("SEA", 200, 200);
that.add(sea);
that.connect(sfo, sea);
if (sea.isConnectedTo(jfk))
{
String err = "Created a FlightNet fn, then fn.connect(sfo, jfk); fn.connect(sfo, sea); ";
err += "Then sea.isConnectedTo(jfk) returned true";
abortZeroPoints(err);
}
if (jfk.isConnectedTo(sea))
{
String err = "Created a FlightNet fn, then fn.connect(sfo, jfk); fn.connect(sfo, sea); ";
err += "Then jfk.isConnectedTo(sea) returned true";
abortZeroPoints(err);
}
// getAirportNearXY
Airport nearest = that.getAirportNearXY(110, 100, 12);
if (nearest != jfk)
{
String err = "FlightNet fn contains SFO at (0, 0), JFK at (100, 100), and SEA at (200, 200) ";
err += "Then that.getAirportNearXY(110, 100, 12) returned " + nearest + ", expected jfk";
abortZeroPoints(err);
}
nearest = that.getAirportNearXY(123456, 123456, 100);
if (nearest != null)
{
String err = "FlightNet fn contains SFO at (0, 0) and JFK at (100, 100) ";
err += "Then that.getAirportNearXY(123456, 123456, 100) returned " + nearest + ", expected null";
abortZeroPoints(err);
}
// removeAndDisconnect.
that.removeAndDisconnect(jfk);
String err = "Created a FlightNet fn, then fn.connect(sfo, jfk); fn.connect(sfo, sea); fn.removeAndDisconnect(jfk); ";
if (that.contains(jfk))
{
err += "Then fn still contains jfk";
abortZeroPoints(err);
}
if (!that.contains(sfo))
{
err += "Then fn no longer contains sfo";
abortZeroPoints(err);
}
if (!that.contains(sea))
{
err += "Then fn no longer contains sea";
abortZeroPoints(err);
}
// Has instance vars?
Field[] fields = fnClass.getDeclaredFields();
if (fields.length > 0)
abortZeroPoints("FlightNet class has " + fields.length + " instance variable(s)");
}
private static void abortZeroPoints(String msg)
{
sop("Zero points: " + msg);
System.exit(1);
}
static void sop(Object x)
{
System.out.println(x);
}
public static void main(String[] args)
{
sop("START");
checkAirport();
checkFlightNet();
sop("DONE");
}
}
Please run the AirGrader to check the grade.
Thank you
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started