堆叠一个 ArrayList

Stack an ArrayList

我正在创建一个程序来自动化火车物流系统,使用 Java。我想用 ArrayList 存储火车:

ArrayList<Train> train = new ArrayList<>();

并在火车列表中添加多个车站:

ArrayList<Stop> stop= new ArrayList<>();
stop.add( new Stop( "Milan", "7", new DepartureTime( (byte) 19, (byte) 35 ) ) );
train.add( new Train( 87569, "Trenitalia", stop ) );

现在我想清除所有停靠点以添加新停靠点:

stop.clear();

但使用此方法可以清除整个 class Train 中的停靠点。如何在 Train class 中存储 ArrayList stop 并使用方法 clear() 而不会丢失停止?

这是Train.java:

public class Train{
  private int number;
  private String owner;
  private ArrayList<Stop> stop = new ArrayList<>();

  Train(int number, String owner, ArrayList<Stop> stop) {
    this.number = number;
    this.owner = owner;
    this.stop = stop;
  }
}

class Stop{
  String station, binary;
  DepartureTime departure;
  ArrivalTime arrival;

  Stop(String station, String binary, DepartureTime departure, ArrivalTime arrival) {
    this.station= station;
    this.binary= binary;
    this.departure= departure;
    this.arrival= arrival;
  }

  Stop(String station, String binary, DepartureTime departure) {
    this.station = station;
    this.binary= binary;
    this.departure= departure;
  }
}

class DepartureTime{
  private byte hour, minute;

  DepartureTime(byte hour, byte minute) {
    this.hour= hour;
    this.minute = minute;
  }

}

class ArrivalTime {
  private byte hour, minute;

  ArrivalTime (byte hour, byte minute) {
    this.hour= hour;
    this.minute = minute;
  }
}

你掉进了一个众所周知的 Java 陷阱:构造函数 Train(int,String,List<Stop>) 的参数 stop 不是 一个(一个实例) ArrayList,它只是对这种实例的 引用

这意味着语句

this.stop = stop;

在该构造函数中不保留该 List 的实例,而只是一个引用。

因此,您应该注意到,当您省略对 stop.clear().

的调用时,所有列车都会有完全相同的停靠站列表。

您现在有两种选择来解决此问题:

  1. 不是在 stop 列表上调用 clear,而是通过调用 new ArrayList<Stop>.

    创建一个新实例
  2. 推荐的方法(因为第一种方法远非防弹……)如下所示:

public class Train
{
  private final int number;
  private final String owner;
  private final List<Stop> stop;

  Train( final int number, final String owner, final List<Stop> stop ) 
  {
    this.number = number;
    this.owner = owner;
    this.stop = List.copyOf( stop );
  }
}

以后如果想操作止损,也可以这样写

this.stop = new ArrayList<>( stop );

即使添加了 stop train,它仍然是您正在清除的相同引用。 因此,创建 Stop ArrayList 的浅表副本并将其添加到 Train,类似这样。

 public static void main(String[] args) throws IOException, GeneralSecurityException {
        ArrayList<Train> train = new ArrayList<>();
        ArrayList<Stop> stop= new ArrayList<>();
        stop.add(new Stop("Milan", "7", new DepartureTime((byte) 19, (byte) 35)));

        ArrayList<Stop>  copyStop = new ArrayList<>(stop);
        train.add(new Train(87569, "Trenitalia", new ArrayList<>(copyStop)));
        stop.clear();

    }