-1

I would like to compare the Objects of two Arrays and obtain a new Array with the Objects that did not match. This is: Array1 Array2 both contain Object User with methods getId and getUsername

    for (int fw = 0; fw < tempOldArray.size(); fw++) {
        for (int fi = 0; fi < tempArray.size(); fi++) {
            if (tempOldArray.get(fw).getId() == tempArray.get(fi).getId()) {
                match++;
                break;
            }
            if(fi == (tempArray.size()-1)) {
                nomatchfound++;
                break;
            }
        }
    }

    Array1: {[1231, Peter], [2562, Jackson], [38987, Robert], [4765, William]}
    Array2: {[2562, Jackson], [7584, Alfred], [38987, Robert], [8123, Mozart]}

    Array3 should output {[1231, Peter], [4765, William]} 
and Array4 should output {[7584, Alfred], [8123, Mozart]}

Also questioned about how to retrieve a result from list

{"peter", "trump", "donald", "jerry"}
{"peter", "donald", "lucas", "jerry"}

and output non matching ones

Vioxini
  • 102
  • 8
  • 1
    Does it have to be done without the help of collections? – Coder Jul 05 '19 at 18:34
  • Ho about using 2 for each with String.equals ()? – bananas Jul 05 '19 at 18:36
  • @Coder He mentioned 'array' but the code example has references to `tempOldArray.size()` which is from Collections. I think it's safe to say he really means `List` – Cuga Jul 05 '19 at 18:38
  • Initialization is ArrayList tempArray = new ArrayList<>(); – Vioxini Jul 05 '19 at 18:42
  • Is adding an equals method to the class you are using an option? As your using an object and have to compare based on the Id, you have to override the equals of the object to make the collections comparison to work. – Coder Jul 05 '19 at 18:53
  • Any solution for new featured example? – Vioxini Jul 05 '19 at 19:09
  • Do *not* go changing the nature of your Question after posting.(a) You make the authors of existing Answers look foolish. (b) You confuse your later readers. Put some effort into drafting and editing your Question *before* you post, not after. Changing my up-vote to a down-vote, and voting to close as unclear. – Basil Bourque Jul 05 '19 at 19:20
  • Sorry Basil. I clearly specified it was a matter of Arrays though I placed afterwards a List example to exemplify what was what I wanted. – Vioxini Jul 05 '19 at 19:22
  • Guys if you don't understand when I meant ARRAY is not my problem. My fault was to exemplify with a List. – Vioxini Jul 05 '19 at 19:44

5 Answers5

2

You could use something like this. With this function it doesn't matter if you compare collection1 with collection2 or collection2 with collection1 if they have different sizes. The diff should be always equal.

private static <E> List<E> getDiff(Collection<E> collection1, Collection<E> collection2) {
    Collection<E> largerOne = collection1.size() >= collection2.size() ? collection1 : collection2;
    Collection<E> smallerOne = largerOne == collection1 ? collection2 : collection1;
    return largerOne.stream().filter(i -> !smallerOne.contains(i)).collect(Collectors.toList());
}
Chr3is
  • 387
  • 5
  • 21
1

If you are already using lists, just use something on the lines of

list1.removeAll(list2)

To further optimize, if you use a hashset, your remove operations become O(1) so it is even more efficient

Aditya
  • 2,148
  • 3
  • 21
  • 34
1

This is simply a matter of discrete math. Check out the implementation of removeAll():

public static void main(String[] args) {
    List<String> first = Arrays.asList("peter", "trump", "donald", "jerry");
    List<String> second = Arrays.asList("peter", "donald", "lucas", "jerry");

    List<String> results = new ArrayList<>(first);
    results.removeAll(second);

    System.out.println(results.toString());
}

Prints:

[trump]

This fulfills your requirement for leaving the first and second Lists intact, and creating a 3rd List to contain the result.

Cuga
  • 17,668
  • 31
  • 111
  • 166
1

The other Answers showing List::removeAll such as the one from Cuga are correct and best for the simple case.

Java streams

I'll show the fancier approach using Java streams. You may want to use this approach if your situation gets more complicated.

Define your two lists. Using List.of to instantiate an unmodifiable list was added to Java 9.

List < String > namesA = List.of ( "Peter" , "Paul" , "Mary" , "Wendy" , "Lisa" );
List < String > namesB = List.of ( "Peter" , "Paul" , "Jesse" , "Wendy" , "Lisa" );

Create a stream from one list. For each element in the stream, see if that element can be found in the other list.

  • To find all the items that match, use
    .filter ( namesB :: contains ).
  • To find all the items that do not match (the distinct elements), use:
    .filter ( Predicate.not ( namesB :: contains ) )

That Predicate.not trick is new to Java 11, as shown here.

Collect the results into a new List.

List < String > distinct =
        namesA.stream ()
                .filter ( Predicate.not ( namesB :: contains ) )
                .collect ( Collectors.toList () );

Dump to console.

System.out.println ( "namesA: " + namesA );
System.out.println ( "namesB: " + namesB );
System.out.println ( "distinct: " + distinct );

Results.

namesA: [Peter, Paul, Mary, Wendy, Lisa]

namesB: [Peter, Paul, Jesse, Wendy, Lisa]

distinct: [Mary]

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

Assuming the class you are using is called Person, you have to add the following equals method to the class definition

@Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }

    if (!Person.class.isAssignableFrom(obj.getClass())) {
        return false;
    }

    final Person other = (Person) obj;

    if (this.id != other.id) {
        return false;
    }

    return true;
}

In this case you can simply use the removeAll method that's specified in the other answers like this.

list1.removeAll(list2);
Coder
  • 2,153
  • 1
  • 16
  • 21
  • This would only provide me if one Object is equal to another Object. But doesn't answer my question of how to make an array out of non-matched objects? If I loop equals method to obtain if the object is the same it can still give me false negative objects because when I loop through two arraylist they will not necessarily be on the same index order. – Vioxini Jul 05 '19 at 19:46
  • removeAll() will take care of removing the matched objects for you – Coder Jul 05 '19 at 19:48
  • tempArray= arrayStatic; tempOldArray= oldArrayStatic; tempArray.add(new Object("PEPO", 12231, "asd", "asds", false)); tempArray.add(new Object("PEPE", 12232, "asd", "asds", false)); tempArray.add(new Object("PEPA", 12233, "asd", "asds", false)); ArrayList results = new ArrayList<>(tempArray); results.removeAll(tempOldArray); – Vioxini Jul 05 '19 at 19:50
  • System.out.println("RESULTADOS" + results.toString()); – Vioxini Jul 05 '19 at 19:51
  • I/System.out: RESULTADOS[] The objects I artificially added to tempArray are not in tempOldArray. – Vioxini Jul 05 '19 at 19:51
  • Is making a class definition not an option for you? I mean creating a new class to hold the data? – Coder Jul 05 '19 at 19:52
  • Why would help me a class definition? I can get the matches already, I just cannot create the new array based on non-matched ones. RemoveAll should work for ArrayList? – Vioxini Jul 05 '19 at 19:53
  • Yes RemoveAll will work for ArrayList. But you need to override the equals method as specified – Coder Jul 05 '19 at 19:54
  • Let me check one second. – Vioxini Jul 05 '19 at 19:55
  • Added your equal method adapted to my object class. Did the substraction. No element was substracted. – Vioxini Jul 05 '19 at 22:00
  • Can I see your code where you are doing the remove ? – Coder Jul 05 '19 at 22:50