首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Guava Hashmap比较

Guava Hashmap比较
EN

Stack Overflow用户
提问于 2021-05-26 23:04:05
回答 1查看 100关注 0票数 0

我在使用芭乐的Maps.difference时遇到了一些问题

现在,使用下面的代码比较来自两个不同jsons的两个HashMaps:

代码语言:javascript
复制
//Create maps from the given jsons
Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();

Map<String, Object> map1 = gson.fromJson(jsonObject1, type);
Map<String, Object> map2 = gson.fromJson(jsonObject2, type);

//Flatten the maps
Map<String, Object> leftFlatMap = FlatMap.flatten(map1);
Map<String, Object> rightFlatMap = FlatMap.flatten(map2);
        
//Check differences between both maps
MapDifference<String, Object> difference = Maps.difference(leftFlatMap, rightFlatMap);

一切运行正常,并且(几乎)正确地比较了所有元素。问题是当HashMap中的一个元素是一个映射数组时,这些元素是相同的,但顺序不同。如下所示:

第一个JSON:

代码语言:javascript
复制
{    "body":[
      {
         "primitive":"VALUE",
         "jsonArray":[
            {
               "element":83284180
            },
            {
               "anotherElement":20832841804
            }
         ]
      }    
    ] 
 }

第二个JSON:

代码语言:javascript
复制
{
   "body":[
      {
         "primitive":"VALUE",
         "jsonArray":[
            {  
               "anotherElement":20832841804
            },
            {
               "element":83284180
            }  
         ]
      }
   ]
}

正如您所看到的,element和anotherElement的值是相同的,但是由于它们在数组中的出现顺序不同,所以difference会显示一个错误。

之前有没有可能对数组进行排序?或任何其他解决方案?

提前感谢!!

EN

回答 1

Stack Overflow用户

发布于 2021-05-27 04:45:43

一种可能的解决方案可能是对内部子数组进行排序,以便影响反序列化映射(然而,我认为在这种情况下从JSON对象生成映射可能不是一个很好的主意,因为反序列化成本和策略不一定代表原始JSON对象)。

假设jsonObject1jsonObject2JsonElement实现,您可以对其后代进行排序。

代码语言:javascript
复制
@UtilityClass
public final class JsonElements {

    public static List<JsonElement> asListView(final JsonArray jsonArray) {
        return new JsonArrayListView(jsonArray);
    }

    public static void sort(final JsonArray jsonArray, final Comparator<? super JsonElement> comparator) {
        Collections.sort(asListView(jsonArray), comparator);
    }

    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    private static final class JsonArrayListView
            extends AbstractList<JsonElement> {

        private final JsonArray jsonArray;

        @Override
        public JsonElement get(final int index) {
            return jsonArray.get(index);
        }

        @Override
        public int size() {
            return jsonArray.size();
        }

        @Override
        @SuppressWarnings("MethodDoesntCallSuperMethod")
        public JsonElement set(final int index, final JsonElement element) {
            return jsonArray.set(index, element);
        }

    }

}
代码语言:javascript
复制
public final class JsonElementsTest {

    private static final Gson gson = new GsonBuilder()
            .disableHtmlEscaping()
            .disableInnerClassSerialization()
            .create();

    private static final Type stringToObjectMapType = new TypeToken<Map<String, Object>>() {}.getType();

    @Test
    public void testSort()
            throws IOException {
        final JsonElement jsonElement1 = ... read the 1st JSON document ...;
        final JsonElement jsonElement2 = ... read the 2nd JSON document ...;
        final JsonArray jsonSubArray1 = getSubArray(jsonElement1);
        final JsonArray jsonSubArray2 = getSubArray(jsonElement2);
        Assertions.assertNotEquals(jsonSubArray1, jsonSubArray2);
        JsonElements.sort(jsonSubArray1, JsonElementsTest::compare);
        JsonElements.sort(jsonSubArray2, JsonElementsTest::compare);
        final Map<String, Object> map1 = gson.fromJson(jsonElement1, stringToObjectMapType);
        final Map<String, Object> map2 = gson.fromJson(jsonElement2, stringToObjectMapType);
        Assertions.assertEquals(map1, map2);
    }

    private static JsonArray getSubArray(final JsonElement jsonElement) {
        return jsonElement.getAsJsonObject()
                .get("body")
                .getAsJsonArray()
                .get(0)
                .getAsJsonObject()
                .get("jsonArray")
                .getAsJsonArray();
    }

    private static int compare(final JsonElement jsonElement1, final JsonElement jsonElement2)
            throws IllegalArgumentException {
        final JsonObject jsonObject1 = jsonElement1.getAsJsonObject();
        final int size1 = jsonObject1.size();
        if ( size1 != 1 ) {
            throw new IllegalArgumentException("Size-1 must equal 1, but was " + size1);
        }
        final JsonObject jsonObject2 = jsonElement2.getAsJsonObject();
        final int size2 = jsonObject2.size();
        if ( size2 != 1 ) {
            throw new IllegalArgumentException("Size-2 must equal 2, but was " + size2);
        }
        // TODO optimize somehow
        final String key1 = jsonObject1.keySet().iterator().next();
        final String key2 = jsonObject2.keySet().iterator().next();
        return key1.compareTo(key2);
    }

}

如果有必要,还可以考虑递归地对子代进行排序。

注意,对于给定的JSON文档,您可能也有一个映射,但我不认为这是您的情况,但如果是这样,那么您可能希望应用@JsonAdapter来应用一个特殊的排序反序列化程序(但是我仍然不认为这也是一个好主意)。或者,也可以为给定的JsonObject创建映射视图,以便它可以生成递归重新排序视图。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67707652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档