1

I have this list:

List<Alarm> localNotifications;

in it I have a bunch of Alarm objects that have a few properties, one of which is a timestamp in milliseconds.

How do I remove Alarm objects with identical times from the list so that only unique timestamps remain in it?

PS: If two alarms have the same timestamp but different properties, either one will do, so I don't care which one will remain in the list.

private class Alarm {
    long timestamp;
    String title;
    String body;
}
Kaloyan Roussev
  • 14,515
  • 21
  • 98
  • 180

4 Answers4

3

You will need to put it through a map first to detect collisions.

Map<Long, Alarm> map = new HashMap<>();
for (Alarm alarm : alarms) {
   map.put(alarm.timestamp, alarm);
}
return map.values();

Or in java8

return alarms.stream()
   .collect(Collectors.toMap(Alarm::timestamp, Function.identity()))
   .values();
dolan
  • 1,716
  • 11
  • 22
  • putIfAbsent seems superfluous and, it's not clear from the question whether losing the ordering of the list is ok or not. – pvg Dec 22 '15 at 22:52
  • putIfAbsent cannot be resolved as a method, as far as I can see it is added in Java 8, but wont work in Java 7, what is the closest best thing? ps: ordering of the list is not important – Kaloyan Roussev Dec 22 '15 at 23:15
  • put() will just overwrite instead of no-oping. – dolan Dec 22 '15 at 23:16
1

Here's a solution using Java 8 streams:

localNotifications.stream()
  .distinct()
  .collect(Collectors.toList());

The distinct method uses Object.equals(Object) methods to compare.

Edit: Streams aren't included in Android's JDK. There's some libraries out there that enable streams, but are pretty hacky. Check out retrolambda if you're interested.

Quy
  • 1,343
  • 9
  • 11
0

Easiest way might be to implement the hashCode() and equals() methods in Alarm, them simply create a new Set from your List.

new Set(localNotifications);

Only unique values will remain.

public class Alarm {
    long timestamp;
    String title;
    String body;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Alarm alarm = (Alarm) o;

        return timestamp == alarm.timestamp;

    }

    @Override
    public int hashCode() {
        return (int) (timestamp ^ (timestamp >>> 32));
    }
}
Patrick Grimard
  • 7,033
  • 8
  • 51
  • 68
0

If a set doesn't work, you could use a TreeMap in order to remove duplicates as well as give you an ordered list of alarms by timestamp, and you wouldn't have to modify the Alarm object.

you could use streaming to add a collection of alarms. Or better yet store them as a TreeMap in the first place.

to convert the Collection to a TreeMap use streaming()

alarmCollection.stream().collect(Collectors.toMap(...))

template here: Java8: convert one map to an another using stream

Community
  • 1
  • 1
brendon
  • 363
  • 3
  • 11