简体   繁体   English

如何测试字符串数组列表的相等性

[英]How to test for equality of Lists of String arrays

I think I can't see the forest for the trees... How do I test for equality (not identity) of all elements recursively in a List of String arrays? 我想我看不到森林的树木...如何在“字符串数组列表”中递归测试所有元素的相等性(而非同一性)? Here's a minimal example: 这是一个最小的示例:

List<String[]> left = new ArrayList<>();
left.add(new String[]{"one", "two"});

List<String[]> right = new ArrayList<>();
right.add(new String[]{"one", "two"});

System.out.println(left.equals(right) ? "Yeah!" : "This is not what I want.");

I want to use this in unit tests. 我想在单元测试中使用它。

A bit more context: I have a class that holds several fields, some of which are List of String arrays and some are Set s of String arrays. 还有一点上下文:我有一个包含几个字段的类,其中一些是String数组List ,而另一些是String数组的Set The class is a result of a parser (actually an intermediate step in a cascade of parsers). 该类是解析器的结果(实际上是解析器级联中的中间步骤)。 In order to test the parser I want to check for equality of instances of the class in question. 为了测试解析器,我想检查所讨论类的实例是否相等。 The IDE-autogenerated equals implementation uses a cascade of Objects.equals invocations on the several List<String[]> and Set<String[]> fields, which is---so I figured---equivalent to the minimal example that I've provided above. IDE自动生成的equals实现在多个List<String[]>Set<String[]>字段上使用Objects.equals调用的级联,这-我认为--等效于我的最小示例以上已提供。

Test that both lists have the same size. 测试两个列表的大小是否相同。 Then if they do, iterate on each of them, and compare each pair of arrays using Arrays.equals() . 然后,如果这样做,则对它们中的每一个进行迭代,并使用Arrays.equals()比较每对数组。

It would be easier if you had a List of lists instead ( List<List<String>> ), because lists can be compared using equals() directly. 如果有一个列表列表( List<List<String>> )会更容易,因为可以直接使用equals()比较列表。

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

import javax.swing.text.html.HTMLDocument.Iterator;


public class test 
{
  public static void main(String args[])
  {

      List<String[]> left = new ArrayList<String[]>();
      left.add(new String[]{"one", "two"});

      List<String[]> right = new ArrayList<String[]>();
      right.add(new String[]{"one", "two"});

      java.util.Iterator<String[]> leftIterator =left.iterator();
      java.util.Iterator<String[]> rightIterator =right.iterator();
      if(left.size() !=right.size())   System.out.println("not equal");
      for(;leftIterator.hasNext();)
      {
         if(Arrays.equals(leftIterator.next(), rightIterator.next())) continue;
         else
         {
             System.out.print("not equal");
             break;
         }
      }


  }
}

You want to compare each list, keep track of if they are equal using a boolean. 您要比较每个列表,并使用布尔值跟踪它们是否相等。 I'm not aware of a single function that will do this directly for you. 我不知道有哪个函数可以直接为您执行此操作。

    List<String[]> left = new ArrayList<>();
    left.add(new String[]{"one", "two"});

    List<String[]> right = new ArrayList<>();
    right.add(new String[]{"one", "two"});

    boolean isEqual = true;
    if (left.size() == right.size())
    {
        // Test for equality
        for (int i = 0; i < left.size(); i++)
        {
            // Compare each array in the list
            if (!Arrays.equals(leftArray, rightArray))
            {
                isEqual = false;
                break;
            }
        }
    }
    else
    {
        // The two list are not even the same length, so are not equal.
        isEqual = false;
    }

    System.out.println(isEqual ? "Yeah!" : "This is not what I want.");

Thanks to everyone for your input. 感谢大家的投入。 This is my resulting code. 这是我的结果代码。

protected static boolean equalsCollectionOfArrays(Collection<? extends Object[]> leftCollection,
                                                   Collection<? extends Object[]> rightCollection) {
    if (leftCollection.size() != rightCollection.size()) {
        return false;
    } else {
        Iterator<? extends Object[]> left = leftCollection.iterator();
        Iterator<? extends Object[]> right = rightCollection.iterator();
        while (left.hasNext()) {
            if (!Arrays.equals(left.next(), right.next())) {
                return false;
            }
        }
        return true;
    }
}

protected static int hashCodeCollectionOfArrays(Collection<? extends Object[]> collection) {
    int hash = 3;
    for (Object[] objects : collection) {
        hash = 67 * hash + Arrays.hashCode(objects);
    }
    return hash;
}

It turned out that my problem was not limited to List<String[]> , but that I ran into the same issues with Set<String[]> and also hashCode() . 原来,我的问题不仅限于List<String[]> ,而且我遇到了Set<String[]>hashCode()的相同问题。 I've ended up with these two methods that I've incorporated into the class' equals and hashCode implementation. 我最后得到了这两种方法,这些方法已合并到类的equalshashCode实现中。 The generic wildcard is not necessary (there are only String arrays), but I just wanted to check out my understanding of generics by the way when I am learning a basic lesson. 通用通配符不是必需的(只有String数组),但是我只是想在学习基础课程时通过方式检查一下对通用的理解。

I am considering to avoid arrays in the future. 我正在考虑避免将来使用数组。 Any comments are very welcome. 任何意见都非常欢迎。

If you need to compare lists, try using equals() of that particular list instance providing another one to compare to. 如果需要比较列表,请尝试使用该特定列表实例的equals()提供另一个要比较的实例。

If you need to compare arrays, try using Arrays.equals() . 如果需要比较数组,请尝试使用Arrays.equals()

If you are doing this in test methods org.junit.Assert 's assertArrayEquals() or assertEquals() should od as they will call those methods behind the covers. 如果在测试方法org.junit.AssertassertArrayEquals()assertEquals()中进行此操作,则它们将被调用,因为它们将在后台调用这些方法。

The Java documentation requires list equals() to behave as you're using it, so your code would work if these were List s of Lists : Java文档需要列表equals()表现为你使用它,因此,如果这些是你的代码将工作ListLists

boolean equals(Object o)

Compares the specified object with this list for equality. 比较指定对象与此列表是否相等。 Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. 当且仅当指定对象也是一个列表,并且两个列表具有相同的大小,并且两个列表中所有对应的元素对相等时,才返回true。 (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. (如果(e1 == null?e2 == null:e1.equals(e2)),则两个元素e1和e2相等。)换句话说,如果两个列表包含相同顺序的相同元素,则两个列表定义为相等。 。 This definition ensures that the equals method works properly across different implementations of the List interface. 此定义确保equals方法可在List接口的不同实现中正常工作。

However at the "leaves" you have plain Java arrays. 但是,在“叶子”处,您具有纯Java数组。 These will use the Object definition of equals , which tests for reference identity, not value equality. 这些将使用equalsObject定义,该定义测试引用身份,而不是值相等。

One way around this in your tests is to write a little helper factory routine that accepts a variable argument list of String s and produces List returns to replace the Java arrays you're currently using. 解决此问题的一种方法是编写一个小的帮助程序工厂例程,该例程接受String的可变参数列表并产生List返回值来替换您当前使用的Java数组。 Then all ought to work fine. 然后所有人都应该工作正常。 Your example would look like this: 您的示例如下所示:

// A little helper to avoid the awkward syntax
// Arrays.asList(new String [] { "one", "two" })
public static List<String> listOf(String ... strings) {
    return Arrays.asList(strings);
}

public static void main(String[] args) {
    List<List<String>> left = new ArrayList<>();
    left.add(listOf("one", "two"));

    List<List<String>> right = new ArrayList<>();
    right.add(listOf("one", "two"));

    System.out.println(left.equals(right) ? "Yeah!" : "This is not what I want.");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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