Java – Remove Items From Linked List

Tags:



I have the following java class with constructor and getters and setters.

public class Train implements Comparable< Train >{
    private String power;      // "steam", "diesel" or "electric"
    private int numPassengers; // total number of passengers 
    private Wagon freight;     // linked list of freight wagons; does not include passenger carriages; 

    public String getPower() {
        return power;
    }
    public void setPower(String power) {
        this.power = power;
    }
    public int getNumPassengers() {
        return numPassengers;
    }
    public void setNumPassengers(int numPassengers) {
        this.numPassengers = numPassengers;
    }
    public Wagon getFreight() {
        return freight;
    }
    public void setFreight(Wagon freight) {
        this.freight = freight;
    }
    @Override
    public int compareTo(Train o) {
        return new Integer(this.getNumPassengers()).compareTo(new Integer(o.getNumPassengers()));
    }

    public Train(String power){
        setPower(power);
        setNumPassengers(0);
        setFreight(null);
    }

    public Train(String power, int pass){
        setPower(power);
        setNumPassengers(pass);
        setFreight(null);       
    }
}

And also another class, wagon which is used by the train class.

class Wagon {
    private String cargo;   // e.g. "wheat"
    private int weight;     // weight of the cargo in tonnes
    private Wagon next;     // the wagon that follows this one in the train; or null if there isn't one

    public String getCargo() {
        return cargo;
    }

    public void setCargo(String cargo) {
        this.cargo = cargo;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Wagon getNext() {
        return next;
    }

    public void setNext(Wagon next) {
        this.next = next;
    }

    public Wagon(String cargo, int weight) {
        setCargo(cargo);
        setWeight(weight);
        setNext(null);
    }

    public Wagon(String cargo, int weight, Wagon next) {
        setCargo(cargo);
        setWeight(weight);
        setNext(next);
    }
}

I initialise a new train like so:

Train trainC2 = new Train("steam", 0);
        trainC2.setFreight(new Wagon("wheat", 400, new Wagon("wheat", 300, new Wagon("maize", 280))));

I want to write a method that takes a train as an input, iterates through the wagons, if the cargo attribute matches a supplied string, the wagon is deleted. I have written this method which creates a new linkedlist and adds the trains wagons to it. It then iterates through this list and removes any matches. I am trying to iterate again through the modified list and use the setFreight method to update the actual train object.

    public static void removeWagons(Train train, String cargo) {
        LinkedList<Wagon> wag8 = new LinkedList<Wagon>();
        wag8.add(train.getFreight());
        ListIterator<Wagon> iter = wag8.listIterator();
        Wagon currentWagon = null;

        while (iter.hasNext()) {
            currentWagon = iter.next();
            System.out.println();

            if (currentWagon.getCargo() == cargo) {
                System.out.println("wag8b4" + wag8);
                iter.remove();
                System.out.println("wag8" + wag8);
                }

            }


        while (iter.hasNext()) {
            train.setFreight(iter.next());
} 

        }

I think I’m close, but don’t know how to write a method that will produce an output like:

trainC2.setFreight(new Wagon("wheat", 400, new Wagon("wheat", 300, new Wagon("maize", 280))));

Or maybe there’s a better way altogether?

Answer

You are not iterating over Wagons because when you call wag8.add(train.getFreight()), now your list has only one Wagon. My suggestion is to write a method named ‘hasNext()’ in your Wagon class so that you can know if there is another Wagon connected to the current wagon. Something like this:

public boolean hasNext(){
    return next!=null;
}

You seem to want to delete some wagons from the middle of the train. Let’s say you want to delete the third wagon. For that, you can change the ‘next’ reference of the second wagon to point to the fourth wagon. Then you have no third wagon!

public static void removeWagons(Train train, String cargo) {
    // First we check the freight is not the matching wagon.
    // If it is we will ignore it
    Wagon freight = train.getFreight();
    Wagon currentWagon = train.getFreight();
    while(currentWagon.getCargo().equals(cargo)){
        freight= currentWagon.next;
        currentWagon=currentWagon.next;
    }
    //We make another wagon to hold a reference to the previous wagon
    Wagon previous=currentWagon;
    //Now the first wagon is alright. So "currentWagon" don't need to be the first
    currentWagon=currentWagon.next;
    
    do{
        if (currentWagon.getCargo().equals(cargo)){
            previous.next=currentWagon.next;
            currentWagon= currentWagon.next;
            continue;
        }
        previous= currentWagon;
        currentWagon= currentWagon.next;
            
    } while(currentWagon.hasNext())
    train.setFreight(freight);
}

Some parts of code are ambiguous. So don’t hesitate to ask how does it work.



Source: stackoverflow