Skwead
Skwead

Reputation: 41

Why does ArrayList.add() modify the object added?

When I add an object to an ArrayList it gets chenged.

I am trying to make a java fx agenda app and so I need to pass an ArrayList with the objects I want in the table to an ObservableList.

The problem happens right in this function, at tableToday.add(ret);

public ArrayList<SkEvent> getTableToday() {
        LocalDateTime clock = LocalDateTime.of(LocalDate.now(), LocalTime.of(0,0));
        while (clock.until(LocalDateTime.of(LocalDate.now(), LocalTime.of(23,59)), ChronoUnit.MINUTES)>0){
            System.out.println("clock: "+clock.toLocalTime().toString());

            SkEvent ret = new SkEvent(LocalDate.now(), clock.toLocalTime());

            if(existsEvent(clock)){
                System.out.println("Event exists.");

                ret = getEvent(clock);
                ret.setLocalDateTime(clock);
            }


            tableToday.add(ret);
            System.out.println("Added event "+ ret.getName() + " at "+ret.getTime().toString());
            LocalDateTime updatedClock = clock.plusMinutes(gap);
            clock = updatedClock;

        }

This is a part of the output:

clock: 21:00
Added event  at 21:00
clock: 21:30
Added event  at 21:30
clock: 22:00
Event exists.
Added event e at 22:00
clock: 22:30
Event exists.
Added event e at 22:30
clock: 23:00
Event exists.
Added event e at 23:00
clock: 23:30
Added event  at 23:30
Times in the table: 
21:00
21:30
23:00
23:00
23:00
23:30

As you can see I add 3 events at 22:00, 22:30 and 23:00, but outputing the event times on the ArrayList outputs 3 times the 23:00

It should output

Times in the table: 
21:00
21:30
22:00
22:30
23:00
23:30

Also, here is the SkEvent class:

public class SkEvent{
    private LocalDate date;
    private LocalTime time;
    private String name;
    private String description;

    public SkEvent(LocalDate date, int hour, int minute, String name, String description) {
        this.date = date;
        this.time = LocalTime.of(hour, minute);
        this.name = name;
        this.description = description;
    }

    public SkEvent(LocalDate date, LocalTime time){
        this.date = date;
        this.time = time;
        this.name = "";
        this.description = "";
    }

    public LocalDateTime getLocalDateTime(){
        return LocalDateTime.of(getDate(), getTime());
    }

    public SkEvent setLocalDateTime(LocalDateTime localDateTime){
        this.date = localDateTime.toLocalDate();
        this.time = localDateTime.toLocalTime();

        return this;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public LocalTime getTime() {
        return time;
    }

    public void setTime(LocalTime time) {
        this.time = time;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

and the getEvent() method:

private Map<SkEvent, LocalDateTime> actualEvents = new HashMap();
//(...)
    private SkEvent getEvent(LocalDateTime clock) {
        for(Map.Entry<SkEvent, LocalDateTime> entry: actualEvents.entrySet()){
            if(!entry.getKey().getLocalDateTime().isAfter(clock) && !entry.getValue().isBefore(clock)){
                return entry.getKey();
            }
        }
        return null;
    }

Many thanks for the time.

Upvotes: 0

Views: 240

Answers (1)

UniqueHorn
UniqueHorn

Reputation: 86

The three unexplained occurrences are:

clock: 22:00
Event exists.
Added event e at 22:00
clock: 22:30
Event exists.
Added event e at 22:30
clock: 23:00
Event exists.
Added event e at 23:00

as you can see on your console: for those three events you entered the if statement (since there was printed "Event exists.".).

if(existsEvent(clock)){
  System.out.println("Event exists.");
  ret = getEvent(clock);
  ret.setLocalDateTime(clock);
}

I can only guess what the used functions are doing, but i assume that existsEvent(clock) returns true if there exists an SkEvent with the same time and date specifiers as clock (actual date) (this is obviously true for the three stated cases above). getEvent(clock) then retrieves this SkEvent and overrides the ret variable with it. ret is then changed (ret.setLocalDateTime(clock)).

tableToday.add(ret) does add a reference (pointing to the SkEvent) to the list. This means, changing the SkEvent object afterwards, will also change its occurrence on the list, since it is only a pointer pointing to the actual (now altered) object.

What you do here is adding a reference referring to a new object to the list, then (3 times) retrieving it, changing it, and adding an additional reference to the same object to this list again.

Upvotes: 2

Related Questions