简体   繁体   中英

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 . 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. 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).

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. 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 . Converting the JSONArray into Collection allows for that quite easily, eg like this

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. It also produces much more iteration then the direct JSONArray API version, which might or might not be a problem. 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.

Please also note that production-ready code would additionally do null checks on arguments.

If you want to USE JAVA Stream API, the object must be Iterable. As @Michal mentioned, you can change it to Collection. From @Michal's answer, we can simplify it, just like:

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

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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