0

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.

9
  • 9
    add doesn't modify the objects. The most likely explanation is you're modifying the object yourself after adding it to the list. Commented Aug 13, 2019 at 18:41
  • 2
    How is the implementation of SkEvent look like? Commented Aug 13, 2019 at 18:41
  • 6
    you are modifying it in if(existsEvent(clock)){ add isn't modifying it at all Commented Aug 13, 2019 at 18:42
  • 1
    @Carcigenicate I double checked your hypotesis, no I do not change the value after adding it. As you can see in my code I output the LocalTime of ret right before adding it and right after adding it iterate over the ArrayList to see it's values' LocalTimes. I mean the modification that happens when adding the object, not the one before it, because the object I try to add is what I want to add, as seen in the output. I'm now adding the code for the SkEvent class and ``getEvent()` method, I didn't think it would be necessary due to what I just explained. Many thanks for the help. Commented Aug 13, 2019 at 19:21
  • 1
    @Skwead add doesn't alter the element: source. Mutation of objects after being put into the list and adding the same element repeatedly is the only explanation I can see here. Commented Aug 13, 2019 at 19:55

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

It was that, when I called setTime() I did not use it on the reference but in the event itself, changing it's time to the end time. I solved it by returning a copy of the event instead of the event itself, thank you :) (You would get an upvote if I had the reputation required)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.