-1

I would like to compare two arrays. I have the following

ArrayList<String> time_durations = new ArrayList<String>();

time_durations.add("1200-1304")
time_durations.add("6-7")

Then the other array has the following structure

ArratList<FetchedData> apiresult = new ArrayList<FetchedData>();
apiresult.add(new FetchedData("1200-1304", //an array of data))

The class fetched data has

class FetchedData{
   private String duration_range;
   private ArrayList data;

  //then setters and getters
  //and also a constructor

 }

So i want to compare the two arrays and get all items contained in time_durations but not in apiresult

Samples of them both in a json format is

time_durations = ["1200-1304", "6-7"]
apiresult = [{duration_range:"1200-1304", data:["item1", "item 2"]}

So by comparison i expect it to return the item in array time_durations6-7 that is index 1

So i have tried

if (Arrays.equals(time_durations, apiresult)) {
    //this throws an error
 }

But the above attempt doesnt work and am stuck.How do i achieve this?

I have checked on This question but still fails

Geoff
  • 6,277
  • 23
  • 87
  • 197

4 Answers4

2

Your code doesn't work as you expected because the first ArrayList is an array of String and the second is an Array of FetchedData. You basically try to compare two ArrayList of different type and this return false by default.

If you want to reach the goals you must map the ArrayList of FetchedData into an ArrayList of String and with Java8 it is possible to do this with a Map function and after you are enable to comparing the two array

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertArrayEquals;

public class TestClass {

    @Test
    public void arrayListComparation(){

        List<String> expected = Arrays.asList("6-7");

        ArrayList<String> time_durations = new ArrayList<String>();
        time_durations.add("1200-1304");
        time_durations.add("6-7");

        ArrayList<FetchedData> apiresult = new ArrayList<>();
        List<String> data = Arrays.asList("item1","item2");
        apiresult.add(new FetchedData("1200-1304", data));

        List<String> apiResultDurationRanges = apiresult.stream().map(FetchedData::getDuration_range).collect(toList());
        time_durations.removeAll(apiResultDurationRanges);

        assertArrayEquals(time_durations.toArray(),expected.toArray());
    }
}

In this example you have on time_durations all element that not appear into apiResult

gccodec
  • 343
  • 1
  • 8
1

You can use Collection.removeAll:

List<String> apiResult_durations = apiresult.stream()
                        .map(FetchedData::getDuration_range)
                        .collect(Collectors.toList());

time_durations.removeAll(apiResult_durations);

After this code, time_durations is only [6-7]
Important to note that this will modify time_durations inline.

If you'd rather not modify it inline, then you can make a copy:

List<String> time_durations_copy = new ArrayList<>(time_durations);
time_durations_copy.removeAll(apiResult_durations);
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • A set is better here. Every `removeAll` implementation I'm aware of uses `Collection.contains` which for a list is O(n) and for a set is O(1). – Michael Jan 17 '19 at 14:10
  • @Michael Possibly. But maybe the list contains duplicates that it should contain. – ernest_k Jan 17 '19 at 14:12
  • The behaviour is exactly the same. – Michael Jan 17 '19 at 14:14
  • 1
    Maybe we're misunderstanding each other here. I meant that if the original list contains duplicates that wouldn't be removed with `removeAll`, then using a `Set` would be introducing a bug (assuming the duplicates are appropriate). But I do agree that if a `Set`-based solution does the job, it would be the one to go for. – ernest_k Jan 17 '19 at 14:16
  • 1
    Whether there are duplicates or not, all copies are removed whether you pass it a list or a set. It seems like you don't know the behaviour of `removeAll`. – Michael Jan 17 '19 at 14:20
  • 1
    @Michael OK, now I'm sure you're misunderstanding me. Take an example: `List(1,1,2,3) minus List(2, 3)`. If you use `removeAll` using a `List`, you get `List(1,1)` as result. If you use a solution based on sets, you get `Set(1)` as a result. And that's probably a bug (one valid duplicate dropped). – ernest_k Jan 17 '19 at 14:24
  • @Michael Thanks for the test, but it's wrong for this scenario. `duplicateList` should be a `Set`. After all, it's the type of the collection on which `removeAll` is invoked that makes the difference. – ernest_k Jan 17 '19 at 14:40
  • I think you misunderstood my comment then. I meant the argument passed **to** `removeAll` should be a set, because removeAll calls `Collection.contains` on the **argument** which in your example is O(n) and if you used `Collectors.toSet` would be O(1). – Michael Jan 17 '19 at 14:49
1

Iterate over the API results, get each duration and put them into a set. Remove the elements of the set from the list.

Set<String> apiDurations = apiresult.stream()
    .map(FetchedData::getDuration)
    .collect(Collectors.toSet());
time_durations.removeAll(apiDurations);
Michael
  • 41,989
  • 11
  • 82
  • 128
1

I think you need the operation of set difference.

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {

        ArrayList<String> time_durations = new ArrayList<String>();//The list with some elements
        ArrayList<String> otherList = new ArrayList<String>();//Another list

        ArrayList<String> difference = new ArrayList<String>();//The result

        time_durations.add("1200-1304");//Add some data
        time_durations.add("6-7");
        otherList.add("1200-1304");

        for (int i = 0; i < time_durations.size(); i++) {
            if (!otherList.contains(time_durations.get(i))) {
                difference.add(time_durations.get(i));        // get all items contained in time_durations but not in apiresult

            }
        }
        for (String string : difference) {
            System.out.println(string);

        }

    }
}