All elements are null:redis操作geo返回List<Point>集合size=1,但实际为null

1 篇文章 0 订阅

前提:使用redis保存经纬度坐标,判断redis中是否存在该坐标时,发现一直判断存在,导致无法存储坐标。

问题代码

//存储redis:查询redis中是否存在该坐标
//member存储经纬度,格式:[经度,纬度]
String member = "["+geoLocation.getLongitude()+","+geoLocation.getLatitude()+"]";
//geoKey可以看作整个经纬度集合的key
List<Point> points = redisGeoUtils.geoGet(geoKey,member);
if (points.size()<=0){
    //不存在,添加至redis
    Point point = new Point(geoLocation.getLongitude(),geoLocation.getLatitude());
    redisGeoUtils.geoAdd(geoKey,point,member);
}

经过debug检查,points.size()一直等于1,导致不能进入添加redis判断。但debug中也发现,points虽然存在元素,但显示的是All elements are null,意思是当前集合所有元素都为null。

原因

List集合允许存入空值,导致出现判断失误。

解决

在原代码中多加一层判断,判断集合中的元素不为null即可。

本处代码redisGeoUtils.geoGet(geoKey,member),是通过总经纬度key与单个经纬度member值获取redis中存储经纬度元素,获取值最多一个,所以只用判断第一个元素不为null即可。

if (points.size()<=0||null==points.get[0]){
...
}

ps:member可以传多个,多个的话就会可能返回多个值,然后再遍历points一个一个判断即可。

    public List<Point> geoGet(String key, String... members) {
        return redisTemplate.opsForGeo().position(key, members);
    }

为何redis不存在,points的size还是返回1,而不是0?

进入geoGet(String key, String… members)方法内部

    public List<Point> geoGet(String key, String... members) {
        return redisTemplate.opsForGeo().position(key, members);
    }

进入position(key, members)

	@Override
	public List<Point> position(K key, M... members) {
		byte[] rawKey = rawKey(key);
		byte[][] rawMembers = rawValues(members);

		return execute(connection -> connection.geoPos(rawKey, rawMembers), true);
	}

进入connection.geoPos(rawKey, rawMembers),选择lettuceGeoCommands.java的实现

	@Override
	public List<Point> geoPos(byte[] key, byte[]... members) {

		Assert.notNull(key, "Key must not be null!");
		Assert.notNull(members, "Members must not be null!");
		Assert.noNullElements(members, "Members must not contain null!");

		ListConverter<GeoCoordinates, Point> converter = LettuceConverters.geoCoordinatesToPointConverter();

		try {
			if (isPipelined()) {
				pipeline(connection.newLettuceResult(getAsyncConnection().geopos(key, members), converter));
				return null;
			}
			if (isQueueing()) {
				transaction(connection.newLettuceResult(getAsyncConnection().geopos(key, members), converter));
				return null;
			}
			return converter.convert(getConnection().geopos(key, members));
		} catch (Exception ex) {
			throw convertLettuceAccessException(ex);
		}
	}

进入converter.convert(getConnection().geopos(key, members))

	@Override
	public List<T> convert(List<S> source) {

		List<T> results = new ArrayList<>(source.size());

		for (S result : source) {
			results.add(itemConverter.convert(result));
		}

		return results;
	}

debug发现convert方法中,source .size=1于是返回的results.size=1,导致最终points.size=1。

在这里插入图片描述
返回上一步,进入getConnection().geopos(key, members),这里是导致source .size=1的原因

    /**
     * Get geo coordinates for the {@code members}.
     *
     * @param key the key of the geo set
     * @param members the members
     *
     * @return a list of {@link GeoCoordinates}s representing the x,y position of each element specified in the arguments. For
     *         missing elements {@literal null} is returned.
     */
    List<GeoCoordinates> geopos(K key, V... members);

该方法没有进一步的实现类,但与直接在redis客户端中使用的方法一样,应该是操作客户端的方法

GEOPOS key member [member …]

根据方法注释解释到:对于缺失元素,返回null。

而在redis官网命令中的解释:
在这里插入图片描述
个人理解:List geopos(K key, V… members)方法在查询到null值后,将null值直接添加至List中,以至于返回size=1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值