Your issue is that you have two completely different notions of what it means for two ChatRoomListModel
objects to be "equal". You provide both compareTo
and operator ==
implementations, but they consider different sets of properties, so compareTo
can return 0 when operator ==
returns false, which is confusing at best. SplayTreeMap
considers only compareTo
, not operator ==
. From the SplayTreeSet
documentation:
Elements of the set are compared using the compare
function passed in the constructor, both for ordering and for equality. If the set contains only an object a
, then set.contains(b)
will return true
if and only if compare(a, b) == 0
, and the value of a == b
is not even checked.
I'm presuming what you call "duplicates" are elements that have equal chatRoomId
s but that have different creation times, and creation times are the only things that your SplayTreeSet
cares about.
If your goal is to maintain only the latest message per chatRoomId
, you need to maintain a data structure that uses the chatRoomId
(a String
) as a key. The natural collection for that would be a Map<String, ChatRoomListModel>
. (Since the ChatRoomListModel
knows its own chatRoomId
, it also could just be a HashSet
with explicit equals
and hashCode
callbacks.)
If you additionally want to keep messages in chronological order, you either will need to explicitly sort them afterward or maintain a separate data structure that keeps them in chronological order. You could continue using a SplayTreeSet
for that. Basically before you add any entry to the SplayTreeSet
, check the Map
first to see if an existing entry for that chatRoomId
.
I don't fully understand your data structures, but here's an example that you presumably can adapt:
import 'dart:collection';
class Message {
Message(this.creationTime, {required this.chatRoomId, required this.text});
final DateTime creationTime;
final String chatRoomId;
final String text;
@override
String toString() => '$creationTime: [$chatRoomId] $text';
}
class Messages {
final _latestMessages = <String, Message>{};
final _orderedMessages = SplayTreeSet<Message>((message1, message2) {
var result = message1.creationTime.compareTo(message2.creationTime);
if (result != 0) {
return result;
}
result = message1.chatRoomId.compareTo(message2.chatRoomId);
if (result != 0) {
return result;
}
return message1.text.compareTo(message2.text);
});
void add(Message message) {
var existingMessage = _latestMessages[message.chatRoomId];
if (existingMessage != null &&
message.creationTime.compareTo(existingMessage.creationTime) < 0) {
// An existing message exists with a later creation date. Ignore the
// incoming message.
return;
}
_latestMessages[message.chatRoomId] = message;
_orderedMessages.remove(existingMessage);
_orderedMessages.add(message);
}
void printAll() => _orderedMessages.forEach(print);
}
void main() {
var messages = Messages();
messages.add(Message(
DateTime(2023, 1, 1),
chatRoomId: 'foo',
text: 'Hello foo!',
));
messages.add(Message(
DateTime(2023, 1, 2),
chatRoomId: 'bar',
text: 'Goodbye bar!',
));
messages.add(Message(
DateTime(2023, 1, 2),
chatRoomId: 'foo',
text: 'Goodbye foo!',
));
messages.add(Message(
DateTime(2023, 1, 1),
chatRoomId: 'bar',
text: 'Hello bar!',
));
messages.printAll();
}