1

我对Java相当陌生,我一直在尝试解决以下问题,但没有成功。

编写一个从给定列表中删除重复项的 Java 方法。

假设:

  1. 方法接受类型 List
  2. 返回类型为void
  3. 重复使用确定equals()

主要的:

  1. 创建一个 List 的瞬间并使用重复的 String 值加载它
  2. 调用removeDuplicates(),传入这个列表
  3. 将修改后的列表输出到控制台。

我可以通过将列表传递给新的 HashSet 并将其复制回来来解决问题。但问题是:

  1. 问题是要求我使用equals()...
  2. 如果返回类型是void,我如何输出它main

导入 java.util.*;公共课问题1 {

    public static void main(String[] args) {
String[] words = {"good","better", "best", "best", "first" , "last", "last", "last", "good"};  
        List<String> list = new ArrayList<String>();  
        for (String s : words) {  
            list.add(s);  
        }  
        removeDuplicates(list);
    }
    static void removeDuplicates(List<String> array){
        HashSet<String> hs = new HashSet<>();
        hs.addAll(array);
        array.clear();
        array.addAll(hs);
        for (String x : array){ 
            System.out.println(x);
        }
    }
}

编辑:嗯,这个工作,但你可以看到我没有使用equals(),我从我的静态方法打印出来,而不是从main。另外,有什么方法可以比使用 String[] 更快地填充列表?

4

4 回答 4

3

java.util.HashSetObject.equals(Object)在其实现中使用Set.add(Object)来确定被插入的元素是唯一的(定义为不等于另一个元素)。HashSet 还具有允许您及时执行重复数据删除过程的优势,而不是O(n)一种更简单的方法,即及时将每个元素与每个其他元素进行比较O(n^2)

中的代码main会看到修改后的列表,因为 List 对象是可变的。当方法更改传入参数的状态时,调用代码将看到这些更改。

于 2013-10-16T14:19:51.640 回答
2
  1. removeDuplicates创建一个set,然后遍历输入列表。如果它遇到输入列表中的元素,也就是集合removeDuplicates中的元素,则从输入列表中删除该元素,否则将元素添加到集合中。
  2. Java 是一种按引用调用的语言(排序)。这意味着,该方法removeDuplicates可以修改它接收到的,调用者将在调用返回List<String> array后看到修改后的列表。removeDuplicates
于 2013-10-16T14:20:57.013 回答
1

可能最简单的方法是首先使用 Set ,根据定义,它不允许重复。

对于您的实际问题,您可以采取几种方法:

  • 简单但缓慢的方法:将每个元素 A 与列表中的其他元素 N 进行比较。如果 A.equals(N) 删除 N。提示:您只需将 A 与每个其他元素进行比较,因为您已经在 A 之前检查了每个元素。

  • 更快的方法:使用自然比较器对列表进行排序。现在您不再需要比较每个元素 A 与 N,而只需比较 A 与接下来的几个元素。确切地说:直到找到不等于 A 的第一个元素。在这种情况下,您可以假设 A 没有进一步的重复(由于排序)并继续将下一个元素作为 A。

  • Map 方法(快速但占用更多内存):对于放入列表中的每个元素,将相同的元素放入 Map 中,并将任何 Object 作为值。现在您可以查找该元素是否已经在地图中,如果是,则它是重复的。

最好的方法是第二种方法,因为排序非常快,您只需要获取每个元素一次,并且不需要第二个列表。

编辑:代码中的第二种方法:

static void removeDuplicates(List<String> array) {
  if (array.size() <= 1) {
    return;
  }
  Collections.sort(array);
  final Iterator<String> it = array.iterator();
  String a = it.next(), n;
  while (it.hasNext()) {
    n = it.next();
    if (((a == null) && (n != null))
            || ((a != null) && (a.equals(n) == false))) {
      a = n;
    } else {
      it.remove();
    }
  }
}
于 2013-10-16T14:22:12.623 回答
1

Set以下是您在不使用 a和仅使用的情况下如何做同样的事情equals()(也可以在某种程度上回答您关于初始化 a 的“编辑”问题List):

  public static void main(String[] args) {
    List<String> list = new ArrayList<String>(Arrays.asList(new String[] {
        "good", "better", "best", "best", "first", "last", "last", "last",
        "good"}));
    removeDuplicates(list);
    for (String x : list) {
      System.out.println(x);
    }
  }

  static void removeDuplicates(List<String> array) {
    for (int i = 0; i < array.size(); i++) {
      String next = array.get(i);

      // check if this has already appeared before
      for (int j = 0; j < i; j++) {
        // if it has, stop the search and remove it
        if (next.equals(array.get(j))) {
          array.remove(i);
          // decrement i since we just removed the i'th element
          i--;
          // stop the search
          break;
        }
      }
    }
  }

也就是说,使用HashSet是一个更好的主意,因为正如已经指出的那样,它更有效。

如果您想要效率HashSet但仍保留您的顺序,List您可以执行以下操作:

  static void removeDuplicates(List<String> array) {
    Set<String> set = new HashSet<String>();

    for (int i = 0; i < array.size(); i++) {
      String next = array.get(i);

      // check if this has already appeared before
      if (!set.add(next)) {
        // if it has then remove it
        array.remove(i);
        // decrement i since we just removed the i'th element
        i--;
      }
    }
  }
于 2013-10-16T14:30:26.317 回答