为什么从redis zset构造的HashSet保持排序?

时间:2019-04-09 10:55:03

标签: redis jedis spring-cache

在Java中,HashSet未排序,如下所示:

        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(4);
        set.add(3);
        set.add(2);
        set.add(5);
        set.forEach(e-> System.out.print(e+" "));

其输出为:

1 2 3 4 5

当Java集合来自zset时,如下所示:

redisTemplate.opsForZSet().add(key, 1, 0);
redisTemplate.opsForZSet().add(key, 4, 1);
redisTemplate.opsForZSet().add(key, 3, 2);
redisTemplate.opsForZSet().add(key, 2, 3);
redisTemplate.opsForZSet().add(key, 5, 4);
Set<Integer> set = redisTemplate.opsForZSet().range(key, 0, -1);
System.out.println(set.getClass());
set.forEach(e-> System.out.print(e+" "));

输出为:

java.util.HashSet
1 4 3 2 5

为什么此时输出保持输入顺序?

2 个答案:

答案 0 :(得分:0)

ZSET由分数排序,而不是ZSET中成员的键。因此,在您的示例中:

redisTemplate.opsForZSet().add(key, 1, 0);
redisTemplate.opsForZSet().add(key, 4, 1);
redisTemplate.opsForZSet().add(key, 3, 2);
redisTemplate.opsForZSet().add(key, 2, 3);
redisTemplate.opsForZSet().add(key, 5, 4);

1的得分为0,而5的得分为4。如果您将其更改为:

redisTemplate.opsForZSet().add(key, 1, 1);
redisTemplate.opsForZSet().add(key, 4, 4);
redisTemplate.opsForZSet().add(key, 3, 3);
redisTemplate.opsForZSet().add(key, 2, 2);
redisTemplate.opsForZSet().add(key, 5, 5);

您应该得到预期的结果。

答案 1 :(得分:0)

jedis不返回纯hashSet,而是返回LinkedHashSet,其中元素是有序的。

package org.springframework.data.redis.serializer;

public abstract class SerializationUtils {
    static <T extends Collection<?>> T deserializeValues(Collection<byte[]> rawValues, Class<T> type,
            RedisSerializer<?> redisSerializer) {
        // connection in pipeline/multi mode
        if (rawValues == null) {
            return null;
        }

        Collection<Object> values = (List.class.isAssignableFrom(type) ? new ArrayList<Object>(rawValues.size())
                : new LinkedHashSet<Object>(rawValues.size()));
        for (byte[] bs : rawValues) {
            values.add(redisSerializer.deserialize(bs));
        }

        return (T) values;
    }
}