从List中删除使用泛型的重复项

时间:2016-09-13 20:29:15

标签: java

问题:我有一个实用程序函数,它接受一个通用列表来删除重复项。现在,当我将它用于List<String>时,匹配应该不区分大小写。代码使用流(Java 8+),我希望保持这种方式。

注意:代码在JAVA 8 +

代码:

public static <T> List<T> removeDuplicates(List<T> inputList) {
    List<T> result = null;
    if (inputList != null && inputList.size() > 0) {
        result = inputList.parallelStream().distinct().collect(Collectors.toList());
    }
    return result;
}

EG:

List<String> inputList = new ArrayList<String>();
inputList.add("a");
inputList.add("A");
inputList.add("abc");
inputList.add("ABC");
inputList.add("c");

当我们致电removeDuplicates(inputList)并打印

值:

 a
 abc
 c

我真的不在乎选择ABC超过abcA超过a,但它应该只有一次。

是否有一种优雅的方法可以在不进行instanceof检查的情况下解决此问题?

3 个答案:

答案 0 :(得分:2)

您可以扩展您的方法以接受在您的信息流中map应用的功能 此函数将具有相同的T通用,因此这将解决对instanceof的需求。在String不区分大小写的示例中,函数将为String::toLowerCase

public static <T> List<T> removeDuplicates(List<T> inputList, Function<T,T> function) {
    List<T> result = null;
    if (inputList != null && inputList.size() > 0) {
        result = inputList.parallelStream()
          .map(function)
          .distinct()
          .collect(Collectors.toList());
    }
    return result;
}

如果您想为不需要它的类型保留相同的API,只需添加此重载:

public static <T> List<T> removeDuplicates(List<T> inputList) {
  return removeDuplicates(inputList, Function.identity());
}

答案 1 :(得分:2)

如果调用者在编译时知道T的类型,您可以让它将可选的Comparator<T>传递给该方法,并使用TreeSet过滤掉重复项:

public static <T> List<T> removeDuplicates(List<T> inputList) {
    // null uses natural ordering
    return removeDuplicates(inputList, null);
}

public static <T> List<T> removeDuplicates(List<T> inputList, Comparator<? super T> comparator) {
    Set<T> set = new TreeSet<>(comparator);
    set.addAll(inputList);
    return new ArrayList<>(set);
}

public static void main(String[] args) {
    System.out.println(removeDuplicates(Arrays.asList(1, 2, 2, 3)));
    System.out.println(removeDuplicates(Arrays.asList("a", "b", "B", "c"), String.CASE_INSENSITIVE_ORDER));
}

输出:

[1, 2, 3]
[a, b, c]

答案 2 :(得分:0)

如果您希望行为与默认等于行为不同,您可以滚动自己的字符串:

import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.stream.Collectors;

public class MyString {
  private final String value;

  public MyString(final String value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return value;
  }

  public String getValue() {
    return value;
  }

  @Override
  public boolean equals(final Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    final MyString myString = (MyString) o;
    return StringUtils.equalsIgnoreCase(myString.value, value);
  }

  @Override
  public int hashCode() {
    return value.toUpperCase().hashCode();
  }

  public static void main(String... args) {
    // args = {aa AA aA bb Bb cc bb CC}
    System.out.println(Arrays.stream(args).map(MyString::new).collect(Collectors.toSet()));
    // prints: [aa, bb, cc]
  }
}