简体   繁体   English

在Java中更新Set的对象

[英]Updating the objects of a Set in Java

I am trying to read from a file and count how many times each string appears in the file. 我正在尝试从文件中读取内容,并计算每个字符串在文件中出现多少次。 I am using a HashSet on the Object Item which i have created as follows : 我在创建的对象项上使用HashSet,如下所示:

Now in my main i am trying to read the file and add each String in the file to my set. 现在在我的主目录中,我试图读取文件并将文件中的每个字符串添加到我的集合中。 Also while adding i am trying to increment the count of an item in the set which is appearing more than once. 另外,在添加时,我试图增加一组中出现多次的项目的计数。 Here's my implementation for that : 这是我的实现:

package pack;

public class Item {

    public String name;
    public int count=1;
    public Item(String name)
    {
        this.name = name;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + count;
        result = prime * result + ((name == null) ? 0 : name.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;
        Item other = (Item) obj;
        if (count != other.count)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

For an input file like this : 对于这样的输入文件:

chair table teapot 椅子桌茶壶
teapot book table 茶壶书桌
chair floor ceiling 椅子地板天花板
wall chair floor 壁椅地板

it is giving an output as follows : 它给出的输出如下:

wall appears 1 times 墙出现1次
book appears 1 times 书出现1次
table appears 2 times 表出现2次
floor appears 2 times 地板出现2次
teapot appears 2 times 茶壶出现2次
chair appears 1 times 椅子出现1次
ceiling appears 1 times 天花板出现1次
chair appears 2 times 椅子出现2次

Here the set is having duplicate elements which i don't want. 在这里,集合中有我不想要的重复元素。 What is the correct way to update the objects inside a set? 更新集中对象的正确方法是什么?

i think this'll help you. 我认为这会对您有所帮助。

Create list of all keywords, and use code below. 创建所有关键字的列表,并在下面使用代码。

public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("a");

        // get all Unique keywords 
        Set<String> set = new HashSet<String>(list);
        for(String keyword: set){
            System.out.println(keyword + ": " + Collections.frequency(list, keyword));
        }
    }

output 输出

b: appears 1 time
a: appears 2 time

Your Implementation is right. 您的实施是正确的。 But your Item class equals method has only problem. 但是您的Item类equals方法只有问题。

In equals method you have used count variable also. 在equals方法中,您还使用了count变量。 But name is only the unique field in that class. 但是名称只是该类中的唯一字段。 You have used count+name as unique. 您已将count + name用作唯一的。 So it will create problem. 因此会产生问题。

HashSet uses hashCode and equals to determine identity, so you should change hashCode and equals to work with the name only when you don't want to include the count of items in the test for equality: HashSet使用hashCodeequals来确定身份,因此仅当您不想在相等性测试中包括项目数时,才应更改hashCodeequals以使用名称:

package pack;

public class Item {

    public String name;
    public int count=1;

    public Item(String name)
    {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.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;
        Item other = (Item) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

I think the problem is in your equals method, when you do this check: 我认为问题出在您的equals方法中,当您执行以下检查时:

if (count != other.count)
        return false;

Your Item class uses the count field in its definition of equals and hashCode. 您的Item类在其equals和hashCode定义中使用count字段。 This means that when you call set.contains(i) for the second occurrence of the string, contains will return true since count==1. 这意味着当您为字符串的第二次出现调用set.contains(i)时,因为count == 1,contains将返回true。 You then increment count, and when you call set.contains(i) for the third occurrence of the string contains will return false, since the count of the Item in the set does not match the count of the Item you are passing to contains. 然后,增量次数,当你调用该字符串的第三次出现set.contains(i)载将返回false,因为的数Item中设置不匹配的计数Item要传递到包含。

To fix this, you should change your definition of equals and hashCode to consider only the string and not the count. 要解决此问题,您应该更改equals和hashCode的定义,使其仅考虑字符串而不考虑计数。

This implementation will work, but is overly complex. 此实现将起作用,但过于复杂。 You could simply create a Map<String, Integer> and increase the Integer (count) each time you see a new occurrence of the string. 您可以简单地创建Map<String, Integer>并在每次看到新出现的字符串时增加Integer(计数)。

Have you considered using a HashMap for your problem: put the name in the key and the counter in the value. 您是否考虑过使用HashMap解决问题:将名称放在键中,将计数器放在值中。 This way you don't need an Item class at all. 这样,您根本不需要Item类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM