简体   繁体   English

如何在Java中比较两个JSONArray?

[英]How do i compare two JSONArray in java?

How do i compare two JSONArray in such a way that, if any value matches in these two, the function must return true . 我该如何比较两个JSONArray,以便如果这两个值匹配,则该函数必须返回true For example: 例如:

array1=={1,2,3,4,5,6} 
array2=={9,10,11,1,12}

When comparing these two arrays the result is true because there is at least one element in common between the two arrays. 比较这两个数组时,结果是true因为两个数组之间至少有一个共同的元素。 Position within the array is not important. 数组中的位置并不重要。

I am trying to compare this through a primitive way (looping through each Array and comparing the value). 我正在尝试通过一种原始方式(在每个Array中循环并比较值)进行比较。

private boolean compareArrays(JSONArray deviation, JSONArray deviationIds) throws JSONException {
for (int i = 0; i < deviation.length(); i++) {
for (int j = 0; j < deviationIds.length(); j++)
if(deviation.getString(i).equals(deviationIds.getString(j)))
    return true;
}
return false;
}

This code works, but i want to know if there is a way i could do this much more professionally. 这段代码有效,但是我想知道是否有一种方法可以更专业地做到这一点。 Maybe, achieve this by using JAVA Stream API. 也许可以通过使用JAVA Stream API来实现。 Please comment if you need any additional information. 如果您需要任何其他信息,请发表评论。 Thanks!! 谢谢!!

The requirement for any match return true can be re-formulated as for non-empty intersection return true . 可以将任何匹配return true的要求重新公式化为非空交集return true Converting the JSONArray into Collection allows for that quite easily, eg like this JSONArray转换为Collection可以很容易地做到这一点,例如这样

public class JsonArrayIntersectTest {

private boolean anyMatch(JSONArray first, JSONArray second) throws JSONException {
    Set<Object> firstAsSet = convertJSONArrayToSet(first);
    Set<Object> secondIdsAsSet = convertJSONArrayToSet(second);
    //Set<Object> intersection = Sets.intersection(firstAsSet, secondIdsAsSet);         // use this if you have Guava
    Set<Object> intersection = firstAsSet.stream()
            .distinct()
            .filter(secondIdsAsSet::contains)
            .collect(Collectors.toSet());
    return !intersection.isEmpty();
}

Set<Object> convertJSONArrayToSet(JSONArray input) throws JSONException {
    Set<Object> retVal = new HashSet<>();
    for (int i = 0; i < input.length(); i++) {
        retVal.add(input.get(i));
    }
    return retVal;
}

@Test
public void testCompareArrays() throws JSONException {
    JSONArray deviation = new JSONArray(ImmutableSet.of("1", "2", "3"));
    JSONArray deviationIds = new JSONArray(ImmutableSet.of("3", "4", "5"));

    Assert.assertTrue(anyMatch(deviation, deviationIds));

    deviation = new JSONArray(ImmutableSet.of("1", "2", "3"));
    deviationIds = new JSONArray(ImmutableSet.of("4", "5", "6"));

    Assert.assertFalse(anyMatch(deviation, deviationIds));

    }
}

However, that is much more code then the initial version using the JSONArray API directly. 但是,这比直接使用JSONArray API的初始版本多得多的代码。 It also produces much more iteration then the direct JSONArray API version, which might or might not be a problem. 与直接JSONArray API版本相比,它还会产生更多的迭代,这可能是问题,也可能不是问题。 In general, I would however argue that it is not a good practise to implement domain logic on transport types such as JSONArray and would always convert into a domain model anyway. 但是,总的来说,我认为在诸如JSONArray这样的传输类型上实现域逻辑不是一个好习惯,并且总会始终转换为域模型。

Please also note that production-ready code would additionally do null checks on arguments. 另请注意,生产就绪型代码还会对参数进行null检查。

If you want to USE JAVA Stream API, the object must be Iterable. 如果要使用JAVA Stream API,则对象必须是可迭代的。 As @Michal mentioned, you can change it to Collection. 如@Michal所述,您可以将其更改为Collection。 From @Michal's answer, we can simplify it, just like: 从@Michal的答案中,我们可以简化它,就像:

public class JsonArrayIntersectTest {

    private boolean anyMatch(JSONArray first, JSONArray second) throws JSONException {
        Set<Object> firstAsSet = convertJSONArrayToSet(first);
        Set<Object> secondIdsAsSet = convertJSONArrayToSet(second);
        // use stream API anyMatch
        return firstAsSet.stream()
                .anyMatch(secondIdsAsSet::contains);
    }

    private Set<Object> convertJSONArrayToSet(JSONArray input) throws JSONException {
        Set<Object> retVal = new HashSet<>();
        for (int i = 0; i < input.length(); i++) {
            retVal.add(input.get(i));
        }
        return retVal;
    }

    @Test
    public void testCompareArrays() throws JSONException {
        JSONArray deviation = new JSONArray(ImmutableSet.of("1", "2", "3"));
        JSONArray deviationIds = new JSONArray(ImmutableSet.of("3", "4", "5"));

        Assert.assertTrue(anyMatch(deviation, deviationIds));

        deviation = new JSONArray(ImmutableSet.of("1", "2", "3"));
        deviationIds = new JSONArray(ImmutableSet.of("4", "5", "6"));

        Assert.assertFalse(anyMatch(deviation, deviationIds));

    }
}

You can use XStream's for handling of JSON mappings 您可以使用XStream来处理JSON映射

http://x-stream.github.io/json-tutorial.html http://x-stream.github.io/json-tutorial.html

Or as per your logic you retrieving string , You can compare as 或者根据您检索字符串的逻辑,您可以将

 JSONCompareResult result = JSONCompare.compareJSON(json1, json2, JSONCompareMode.STRICT);
 System.out.println(result.toString());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM