2016-09-13 82 views
-1

问题:我有一个实用函数,它接受一个通用列表来删除重复项,现在当我使用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 

我真的不关心,如果它选择了aABCabcA,但它应该有一次。

有没有一个优雅的方式解决这个问题,而不是做一个instanceof检查?

+6

你为什么不只是转换了'List'到'Set'? –

+3

如果你只处理'String',为什么要使方法通用? – Jezor

+2

@MatthewDiana它仍然不会解决我的问题。设置删除重复项,但不检查不区分大小写的部分... – StackFlowed

回答

2

,你可以把它传递一个可选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

您可以将您的方法扩展为接受在您的流上应用map的功能。
此功能将与通用T相同,所以这将解决对instanceof的需求。在字符串不区分大小写的示例中,函数将是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对于不需要它的类型,只需添加此重载:如果来电者知道的T在编译时类型

public static <T> List<T> removeDuplicates(List<T> inputList) { 
    return removeDuplicates(inputList, Function.identity()); 
} 
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] 
    } 
}