好的,这是我的问题.我必须使用HashSet,我使用removeAll方法从另一个集合中删除存在的值.
在调用该方法之前,我明显地将值添加到集合中.在添加之前,我在每个String上调用.toUpperCase(),因为两个列表中的值都是不同的.没有韵律或理由.
一旦我打电话给removeAll,我需要把原来的案例返回给Set中留下的值.在没有运行原始列表并使用CompareToIgnoreCase的情况下,是否有效的方法?
例:
列表1:
"BOB" "Joe" "john" "MARK" "dave" "Bill"
列表2:
"JOE" "MARK" "DAVE"
之后,在Strings上使用toUpperCase()为每个列表创建一个单独的HashSet.然后调用removeAll.
Set1.removeAll(set2); Set1: "BOB" "JOHN" "BILL"
我需要重新列出这个列表:
"BOB" "john" "Bill"
任何想法都将不胜感激.我知道它很差,应该有一个标准的原始名单,但这不是我决定.
解决方法
在我原来的答案中,我无意中建议使用比较器,但这会导致TreeSet违反
equals
contract,并且是一个等待发生的错误:
// Don't do this: Set<String> setA = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); setA.add("hello"); setA.add("Hello"); System.out.println(setA); Set<String> setB = new HashSet<String>(); setB.add("HELLO"); // Bad code; violates symmetry requirement System.out.println(setB.equals(setA) == setA.equals(setB));
最好使用专用的类型:
public final class CaselessString { private final String string; private final String normalized; private CaselessString(String string,Locale locale) { this.string = string; normalized = string.toUpperCase(locale); } @Override public String toString() { return string; } @Override public int hashCode() { return normalized.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof CaselessString) { return ((CaselessString) obj).normalized.equals(normalized); } return false; } public static CaselessString as(String s,Locale locale) { return new CaselessString(s,locale); } public static CaselessString as(String s) { return as(s,Locale.ENGLISH); } // TODO: probably best to implement CharSequence for convenience }
Set<CaselessString> set1 = new HashSet<CaselessString>(); set1.add(CaselessString.as("Hello")); set1.add(CaselessString.as("HELLO")); Set<CaselessString> set2 = new HashSet<CaselessString>(); set2.add(CaselessString.as("hello")); System.out.println("1: " + set1); System.out.println("2: " + set2); System.out.println("equals: " + set1.equals(set2));
不幸的是,这是更冗长的.