【问题标题】:contains() method not working包含()方法不起作用
【发布时间】:2017-04-24 10:15:14
【问题描述】:
private List<String> values = new ArrayList<String>();

public WhitespaceEqualsTest() {
    values.add("I ");
    values.add("I");
    values.add(". ");
    values.add(".");
    values.add("1");
    values.add("1 ");

    System.out.println(refine(values));
}

private List<String> refine(List<String> input){
    ArrayList<String> outerLoopValues = (ArrayList<String>) input;
    ArrayList<String> innerLoopValues = (ArrayList<String>) input;
    ArrayList<String> results = new ArrayList<String>();

    for(String string1 : outerLoopValues){
        for(String string2 : innerLoopValues){
            if(string1.contains(string2) == false){
                results.add(string1);
            }
        }
    }

    Set<String> temp = new HashSet<String>();
    temp.addAll(results);
    results.clear();
    results.addAll(temp);

    return results;
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((values == null) ? 0 : values.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    WhitespaceEqualsTest other = (WhitespaceEqualsTest) obj;
    if (values == null) {
        if (other.values != null)
            return false;
    } else if (!values.equals(other.values))
        return false;
    return true;
}

我已经覆盖了hashCode()equals(),所以我不太确定出了什么问题。它们是使用 Eclipse 生成的(Source -> Generate hashCode() 和 equals())。为什么没有检测到没有空格的相同字符包含在有空格的字符中?输出是:

[1, . , I , I, ., 1 ]

【问题讨论】:

  • 为什么不一直使用 ArrayList 来代替列表呢?
  • 我有点怀疑您是否已将 hashCode()equals(String) 覆盖为 java.lang.String。请提供该代码。您只提供了一个测试,该测试(似乎)可以完全按照Strings 的方式工作。
  • OP 把所有东西都扔进一个集合,然后又回到列表中,所以他绝对不能超过 6 场比赛。
  • OP,你已经为你的类覆盖了 equals 和 hashcode。当您在 List&lt;String&gt; 上调用 contains 时,不会调用这些。只会使用String#equalsList 实现(在本例中为 ArrayList)完全不知道您的 WhitespaceEqualsTest 类。
  • @AlexQuilliam 不要使用字符串。制作一个自定义字符串包装器并使用它,然后您可以覆盖 equals 和 hashCode 方法

标签: java string contains


【解决方案1】:

String 类是最终的。所以你不能覆盖它的 equals 和 hashCode 方法。

private List<StringWrapper> values = new ArrayList<StringWrapper>();

public WhitespaceEqualsTest() {
    values.add(new StringWrapper("I "));
    values.add(new StringWrapper("I"));
    values.add(new StringWrapper(". "));
    values.add(new StringWrapper("."));
    values.add(new StringWrapper("1"));
    values.add(new StringWrapper("1 "));

    System.out.println(refine(values));
}

private List<StringWrapper> refine(List<StringWrapper> input){
    //no need to iterate the list
    //the set will automatically cancel out the duplicate
    Set<StringWrapper> temp = new HashSet<StringWrapper>(input);

    ArrayList<StringWrapper> results = new ArrayList<StringWrapper>();
    results.addAll(temp);
    return results;
}

创建一个 String 的包装类,然后覆盖 equals 和 hashcode 方法。

class StringWrapper {
    private String value;

    public StringWrapper(String value){
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
    @Override
    public String toString(){
        return value;
    }
    @Override
    public boolean equals(Object obj){
        boolean result = Boolean.FALSE;
        if(obj != null && obj instanceof StringWrapper){
            StringWrapper stringWrapper = (StringWrapper) obj;
            result = value.trim().equals(stringWrapper.getValue().trim());
        }
        return result;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value.trim() == null) ? 0 : value.trim().hashCode());
        return result;
    }
}

【讨论】:

    【解决方案2】:

    您将值添加到集合中。在任何情况下,在一个集合中,一个值出现一次 - 因此它是一个集合。 ;)

    你不妨修改一下循环看看会发生什么

    for(String string1 : outerLoopValues){
                for(String string2 : innerLoopValues){
                    if(string1.contains(string2) == false){
                        results.add(string1);
                        System.out.println("added \"" + string1 + "\" since it does not contain \"" + string2 + "\"");
                    }
                }
            }
    

    给出以下输出:

    added "I " since it does  not contain ". "
    added "I " since it does  not contain "."
    added "I " since it does  not contain "1"
    added "I " since it does  not contain "1 "
    added "I" since it does  not contain "I "
    added "I" since it does  not contain ". "
    added "I" since it does  not contain "."
    added "I" since it does  not contain "1"
    added "I" since it does  not contain "1 "
    ......
    [1, . , I , I, ., 1 ]
    

    如果它们不包含彼此,则添加它们是我猜的想法?

    然后通过 Set 推动 List 删除重复项!见这里:Does adding a duplicate value to a HashSet/HashMap replace the previous value

    将循环中的条件从 false 更改为 true 会产生这种情况(在输出的最后一行中使用 Set/HashSet 后没有变化!)

    added "I " since it does contain "I "
    added "I " since it does contain "I"
    added "I" since it does contain "I"
    added ". " since it does contain ". "
    added ". " since it does contain "."
    added "." since it does contain "."
    added "1" since it does contain "1"
    added "1 " since it does contain "1"
    added "1 " since it does contain "1 "
    [1, . , I , I, ., 1 ]
    

    这回答了您的问题:它确实可以检测到,例如“我”包含“我”。

    System.out.println("I ".contains("I"));
    

    说“真的”

    希望对你有所帮助^^-d

    【讨论】:

    • 好吧,如果是这样的话,如果它工作正常,不是只有 3 个值吗?
    • 不,您的 6 个值至少在该集合起作用的代码部分是“唯一的”。在集合中“我”不是“我”和“。”不是 ”。 ”。 stackoverflow.com/questions/12940663/…
    • 设置不是这里的问题,尝试运行没有设置sn-p的代码。
    • Set&lt;String&gt; temp (结果列表中有多个输入字符串)设置断点,在return results;设置断点,每个输入字符串只包含一次。
    • @AlexQuilliam 检查条件是否从假变为真时的输出。 (此答案中的第二个输出)^^
    【解决方案3】:

    正如其中一个 cmets 所述,您应该使用 String 包装器来包装字符串并覆盖 equals 和 hashcode 方法。

    我的解决方案是基于"I " 应该等于"I" 的假设,因此只应将其中一个添加到结果中。

    但是我需要根据Java Objects 中的文档添加它 和Java Arraylist 分别与equalscontains 实现有关。 hashcode 方法必须返回一个公共值。我已将代码中的解释写为 cmets。如果有任何问题,请告诉我。

    主类

    public class StackOverflowMain
    {
        private static List<String> values = new ArrayList<String>();
    
        public static void main(String[] args) {
    
            values.add("I ");
            values.add("I");
            values.add(". ");
            values.add(".");
            values.add("1");
            values.add("1 ");
            List<WhitespaceEqualsTest> toRefineList = new ArrayList<WhitespaceEqualsTest>();
            for (String value : values) {
                toRefineList.add(new WhitespaceEqualsTest(value));
            }
    
            System.out.println(refine(toRefineList));
        }
    
        private static List<WhitespaceEqualsTest> refine(List<WhitespaceEqualsTest> input) {
            ArrayList<WhitespaceEqualsTest> loopValues = (ArrayList<WhitespaceEqualsTest>) input;
            ArrayList<WhitespaceEqualsTest> results = new ArrayList<WhitespaceEqualsTest>();
    
            for (WhitespaceEqualsTest value : loopValues) {
                if (!results.contains(loopValues)) {
                    results.add(value);
                }
            }
    
            Set<WhitespaceEqualsTest> temp = new HashSet<WhitespaceEqualsTest>();
            temp.addAll(results);
            results.clear();
            results.addAll(temp);
    
            return results;
    
        }
    }
    

    内部WhitespaceEqualsTest

    class WhitespaceEqualsTest {
        private String value;
    
        public WhitespaceEqualsTest(String value) {
            this.value = value;
        }
    
        public void setString(String value) {
            this.value = value;
        }
    
        public String getString() {
            return this.value;
        }
    
        public int hashCode() {
            /*
             * Arraylist.contains is evaluated by using (o==null ? e==null : o.equals(e)) as mentioned in the javadoc
             * and Object.equals() would evaluate using hashcode() first to check if the object o is equal to object e
             * before calling .equals() method to evaluate.
             * 
             * As mentioned in java doc at http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#equals(java.lang.Object)
             * c1.equals(c2) implies that c1.hashCode()==c2.hashCode() should be satisfied
             * which is not in this question
             */      
            return 0;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            WhitespaceEqualsTest other = (WhitespaceEqualsTest) obj;
            if (value == null) {
                if (other.value != null)
                    return false;
            } else if (!value.contains(other.value) && !other.value.contains(value)){ 
                /*
                 * Does a checking on both ends since "I " contains "I" but "I" does not contain "I " due to the whitespace
                 * For this question, if one of the condition satisfy it should be equal
                 */
                return false;
            }           
            return true;
        }
    
        @Override
        public String toString() {
            return this.value;
        }
    }
    

    结果

    [I , . , 1]
    

    【讨论】:

    • 这可能是 OP 打算做的。我看到您为此付出了努力,但您没有回答问题Why isn't it detecting that the same character without a space is contained within a character with a space?问候
    • 查看 equals 方法,我已经在那里添加了 cmets。为简单起见,OP 在“覆盖”equals() 中使用了object.equals(),在使用.equals() 评估之前,java 将使用hashcode() 评估它,在OP 代码中,每个字符串都有一个唯一的哈希码。由于哈希码不同,它返回 false,因此不等于。但这不是这个问题的目的,而是 hashcode() 不应返回唯一值,String.contains() 应在覆盖的 .equals() 方法中使用以进行评估。
    • 是的,它很棒,但是这个问题是关于 contains 方法的(标题是 contains() 方法不起作用)。而"I ".contains("I") 无论如何都会产生 true 。 System.out.println("I ".contains("I")); 如果你愿意的话。 :)
    • 是的,没错,OP 代码已经反映了这一点。正如我的假设中提到的,这个解决方案反映了这一点。在 OP 代码中,循环还有另一个问题,它创建了数组的笛卡尔积,因此返回了 cmets 中提到的所有 6 个值。
    • 当然,您可以摆脱在字符串包装器中覆盖哈希码和 .equals 方法的所有这些麻烦,并在迭代本身期间实现逻辑。此代码是基于 OP 意图构建的,该意图也已用于其他原因。真的取决于你。
    猜你喜欢
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多