暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Jedis Api返回的Set,真的是“Set”?

菜鸟问路 2021-06-21
1343


问题背景


公司对旧项目进行重构,需要将数据迁移到新系统。
会先确定好需要迁移的用户范围,然后将这批用户id
放到redis
set
中,与用户相关联的数据,都会基于这个数据范围进行迁移。
很自然的想到了 Java
集合中的 contains
方法.常用集合中 set
map
api
的时间效率是 O(1)
,而list
的时间效率是 O(n)
(使用的是遍历比较)。
实际迁移过程,发现 smembers
返回的 set
在过滤效率上与 list
基本没差别。
这与理论是不符的

通过对源码的查看,发现这货返回的是SetFromList
      public Set<String> smembers(final String key) {
    checkIsInMultiOrPipeline();
    client.smembers(key);
    final List<String> members = client.getMultiBulkReply();
    if (members == null) {
    return Collections.emptySet();
    }
    return SetFromList.of(members);
      }
    SetFromList
    只是一个装饰器,虽然继承 AbstractSet
    但内部有个 list
    变量存储具体的数据。所有的操作都会转成对 list
    结构的操作。因此在性能、顺序性、并发等特性上,都与 list
    是一致的(典型的挂羊头卖狗肉)

    通过对其他返回set的api进行查看,jedis
    大部分返回 Set
    类型的 api
    ,实际返回的都是 SetFromList
     。

    问题解决

    知道问题所在,那么也就好解决了。可以将返回的结果再重新new HashSet()
    进行转换。

    当然,也可以使用其他的redis
    客户端,如SpringData RedisTemplate
    ,该客户端在对返回数据进行序列化时,如果发现结果是 List
    类型,会转成 ArrayList
    返回,否则转成 LinkedHashSet
     。

    基础知识

    Java中,常用集合:ListSetMapcontains方法上,其时间效率依次为:O(n),O(1),O(1).

      // hashSet中的contains
      public boolean contains(Object o) {
      return map.containsKey(o);
      }


      // hashMap的containsKey
      public boolean containsKey(Object key) {
      return getNode(hash(key), key) != null;
      }


      // arrayList的contains
      public boolean contains(Object o) {
      return indexOf(o) >= 0;
      }


      // indexOf会进行顺序遍历
      // 然后再判断对应值是否相等
      public int indexOf(Object o) {
      if (o == null) {
      for (int i = 0; i < size; i++)
      if (elementData[i]==null)
      return i;
      } else {
      for (int i = 0; i < size; i++)
      if (o.equals(elementData[i]))
      return i;
      }
      return -1;
      }



      基础扎实,遇事不慌。



      文章转载自菜鸟问路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论