java: List of String Arrays and remove

2019-02-16 14:45发布

问题:

In a test like this:

    @Test
    public void test() {
        List<String[]> l = new LinkedList<String[]>();
        l.add(new String [] {"test", "123"});
        l.add(new String [] {"test", "456"});
        l.add(new String [] {"test", "789"});

        assertEquals(3, l.size());

        l.remove(new String [] {"test", "456"});

        assertEquals(2, l.size());
    }

the second assertion(=2) fails as the equals/hashcode used in list.remove are the default for Object. Is there a way to make the list able to use Arrays.equals/Arrays.hashcode to compare the arrays? Or the only solution is wrapping the String arrays in an object and overriding equals/hashcode?

回答1:

Using Guava, there is. You will need to implement an Equivalence<String[]>:

public final class MyEquivalence
    extends Equivalence<String[]>
{
    @Override
    protected boolean doEquivalent(final String[] a, final String[] b)
    {
        return Arrays.equals(a, b);
    }

    @Override
    protected int doHash(final String[] t)
    {
        return Arrays.hashCode(t);
    }
}

You would then need to have your list being a List<Equivalence.Wrapper<String[]>>, and insert/remove/etc using your Equivalence's .wrap() method:

final Equivalence<String[]> eq = new MyEquivalence();
list.add(eq.wrap(oneValue));
list.remove(eq.wrap(anotherValue));

Use Guava. Repeat after me. Use Guava :p



回答2:

You are creating a new Object reference and passing it to the remove() method . From the data you posted , it looks like you can create a custom class with two properties and override its equals() and hashCode() instead of storing them as String[] OR Keep the reference to the String[] object inserted and use that reference to remove.



回答3:

The List method are often based on the Object method equals(Object o) which compare the object's reference by default. You may store the tab if you want remove it later, or create your own class and override equals(Object o) ;)

    @Test
    public void test() {
        List<String[]> l = new LinkedList<String[]>();
        l.add(new String [] {"test", "123"});
        String[] tab = new String [] {"test", "456"};
        l.add(tab);
        l.add(new String [] {"test", "789"});

        assertEquals(3, l.size());

        l.remove(tab);

        assertEquals(2, l.size());
    }


回答4:

By the way, Java 8 introduces a new removeIf method that removes all of the elements of this collection that satisfy the given predicate

It can be used to easily remove an array of strings from the list:

List<String[]> l = new LinkedList<String[]>();
l.add(new String [] {"test", "123"});
l.add(new String [] {"test", "456"});
l.add(new String [] {"test", "789"});

String[] newArray = new String[] {"test", "456"};
l.removeIf(array -> Arrays.equals(array, newArray));


标签: java list junit