问题:我有一个实用程序函数,它接受一个通用列表来删除重复项。现在,当我将它用于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
超过abc
或A
超过a
,但它应该只有一次。
是否有一种优雅的方法可以在不进行instanceof
检查的情况下解决此问题?
答案 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]
}
}