How to compare two ArrayList and output value

122 views Asked by At

Without using GSON.

I'm attempting to pull the text value from the 'chores' array if there is a matching value in 'chore' array within myFilterObj object.

{
    "chores": [
        {
            "text": "Wash the car",
            "value": 1
        },
        {
            "text": "Mow the lawn",
            "value": 2
        },
        {
            "text": "Vaccumm the floor",
            "value": 3
        },
        {
            "text": "Walk the dog",
            "value": 4
        }
    ],
    "myFilterObj": {
        "chore": [
            1,
            2
        ]
    }
}

The first thing I did was convert them to ArrayLists.

Below are the two ArrayLists. My goal is to printout the text from first ArrayList if that value is in the second ArrayList.

For Example: Wash the car and Vaccumm the floor should printout since 1 and 2 are in the second ArrayList and 1 and 2 are values in the first ArrayList.

Here is what I have so far. I'm stuck on trying to do the comparison for allChores.value to value. I think I should be using removeAll or contains??

JSONArray allChores = data.getJSONArray("chores");
JSONArray myChores = myFilterObj.getJSONArray("chore"); 
ArrayList<Object> listdata1 = new ArrayList<Object>();
ArrayList<Object> listdata2 = new ArrayList<Object>();
if (allChores != null) {
    for (int i = 0; i < allChores.length(); i++) {
        //Adding each element of JSON array into ArrayList
        listdata1.add(allChores.get(i));
    }
}
if (myChores != null) {
    for (int i = 0; i < myChores.length(); i++) {
        //Adding each element of JSON array into ArrayList
        listdata2.add(myChores.get(i));
    }
}
//comapare allChores.value to myChores(value)
//printout allChores.text on match 
[ 
    {
        "text":"Wash the car",
        "value":1
    }, 
    {
        "text":"Mow the lawn",
        "value":7
    }, 
    {
        "text":"Vaccumm the floor",
        "value":2
    }, 
    {
        "text":"Walk the dog",
        "value":8
    }
]
[
    1,
    2,
    3
]
2

There are 2 answers

3
Valerij Dobler On

The following answer was composed under the assumption, that GSON can be used.

I would start by converting the input into POJOs. For that, I would introduce for every object in the input a separate record Chore, McChores and Input itself.

record Chore(int value, String text) {
}

record MyChores(List<Integer> chore) {
}

record Input(List<Chore> chores, MyChores myFilterObj) {
}

Such that you can then create look up map of the chores

public static void main(String[] args) {
    final var data = """
            {
                "chores": [
                    {
                        "text": "Wash the car",
                        "value": 1
                    },
                    {
                        "text": "Mow the lawn",
                        "value": 2
                    },
                    {
                        "text": "Vaccumm the floor",
                        "value": 3
                    },
                    {
                        "text": "Walk the dog",
                        "value": 4
                    }
                ],
                "myFilterObj": {
                    "chore": [
                        1,
                        2,
                        7
                    ]
                }
            }
            """;
    final var input = new Gson().fromJson(data, Input.class);
    final Map<Integer, String> choresLookup = input.chores().stream()
            .collect(Collectors.toMap(Chore::value, Chore::text));
    final var myChores = input.myFilterObj().chore().stream()
            .filter(choresLookup::containsKey) // absent values gets filtered out
            .map(choresLookup::get)
            .toList();
}

Results in

[Wash the car, Mow the lawn]
4
Valerij Dobler On

A little bit overkill but my preferred solution would be to create a lookup map for the chores and then iterate over the IDs to generate the labels.

private static Map<Integer, String> makeLookupMap(JSONArray chores) {
    final var result = HashMap.newHashMap(chores.length()); // new since Java 19
    for (Object entry : chores) {
        JSONObject chore = (JSONObject) entry;
        int id = chore.getInt("value");
        String label = chore.getString("text");
        result.put(id, label);
    }
    return result;
}

Then the processing of the input is more or less the same as my GSON solution but with more procedural processing because the JSONArrays is already an Iterable otherwise it would need to be converted twice (Iterable -> List -> Stream).

public static void main(String[] args) {
    final var data = ""/* as before */;
    final JSONObject input = new JSONObject(data);
    final JSONArray chores = input.getJSONArray("chores");
    final Map<Integer, String> choresLookup = makeLookupMap(chores);
    final List<String> myChores = new ArrayList<>();
    final var choreIds = input.getJSONObject("myFilterObj").getJSONArray("chore");
    for (Object choreId : choreIds) {
        final var id = (int) choreId;
        if (choresLookup.containsKey(id)) {
            myChores.add(choresLookup.get(id));
        }
    }
    System.out.println(myChores);
}

which also results in

[Wash the car, Mow the lawn]