利用TreeSet进行消息去重

业务场景

在聊天软件中,发送方发送消息时,遇到网络超时后就会自动重发,因此,接收方可能会收到重复的消息,在显示给用户看的时候,需要首先去重

样板代码

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;
    }
}
代码实现
  1. 利用set无法保证顺序
HashSet<Integer> objects = new HashSet<>();
        //返回的消息
        List<Message> res = new ArrayList<>();
        for (Message message : received) {
            if (objects.add(message.sequence)) {
                res.add(message);
            }
        }

存在问题:无法保证有序
解决方法:使用TreeSet

  1. 使用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);
   }
}

存在问题:有没有更优雅的代码实现

  1. 最优解代码
   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表达式魅力,简洁易读
就是出现问题不好究因
建议:没有深厚开发基础的慎用

总结:

  1. 代码不仅要追求性能,更要易读,易维护,这是第一原则
  2. 有趣的精进代码,能启发思维,开阔视野
  3. 勤学苦练,熟能生巧:写代码是个过程,是一步一步写出来的,能举一反三
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值