业务场景
在聊天软件中,发送方发送消息时,遇到网络超时后就会自动重发,因此,接收方可能会收到重复的消息,在显示给用户看的时候,需要首先去重
样板代码
public class Main {
public static void main(String[] args) {
List<Message> received = List.of(
new Message(1, "Hello!"),
new Message(2, "发工资了吗?"),
new Message(2, "发工资了吗?"),
new Message(4, "Bye"),
new Message(3, "去哪吃饭?"),
new Message(3, "去哪吃饭?")
);
List<Message> displayMessages = process(received);
for (Message message : displayMessages) {
System.out.println(message.text);
}
}
static List<Message> process(List<Message> received) {
// TODO: 按sequence去除重复消息
return received;
}
}
class Message {
public final int sequence;
public final String text;
public Message(int sequence, String text) {
this.sequence = sequence;
this.text = text;
}
}
代码实现
- 利用set无法保证顺序
HashSet<Integer> objects = new HashSet<>();
//返回的消息
List<Message> res = new ArrayList<>();
for (Message message : received) {
if (objects.add(message.sequence)) {
res.add(message);
}
}
存在问题:无法保证有序
解决方法:使用TreeSet
- 使用TreeSet实现有序性
private static List<Message> processTwo(List<Message> received) {
TreeSet<Message> messageSet = new TreeSet<>(new Comparator<Message>() {
@Override
public int compare(Message m1, Message m2) {
//优化后的
// return (m1.sequence - m2.sequence);
//这个是最优解
// Integer cm1 = new Integer(m1.sequence);
// Integer cm2 = new Integer(m2.sequence);
// return cm1.compareTo(cm2);
if (m1.sequence == m2.sequence) {
return 0;
}
return m1.sequence > m2.sequence ? 1 : -1;
}
});
messageSet.addAll(received);
return new ArrayList<>(messageSet);
}
对应的实体类Message更改如下:
class Message {
public final int sequence;
public final String text;
public Message(int sequence, String text) {
this.sequence = sequence;
this.text = text;
}
@Override
public boolean equals(Object o) {
if (this == o) {return true;}
if (o == null || getClass() != o.getClass()) {return false;}
Message message = (Message) o;
return sequence == message.sequence &&
Objects.equals(text, message.text);
}
@Override
public int hashCode() {
return Objects.hash(sequence, text);
}
}
存在问题:有没有更优雅的代码实现
- 最优解代码
private static List<Message> processThree(List<Message> received) {
//这个最优解-太简洁了
TreeSet<Message> set = new TreeSet<>(Comparator.comparingInt(m -> m.sequence));
set.addAll(received);
return new ArrayList<>(set);
}
这是使用lambda表达式魅力,简洁易读
就是出现问题不好究因
建议:没有深厚开发基础的慎用
总结:
- 代码不仅要追求性能,更要易读,易维护,这是第一原则
- 有趣的精进代码,能启发思维,开阔视野
- 勤学苦练,熟能生巧:写代码是个过程,是一步一步写出来的,能举一反三