15

在我发布这个问题之前,我发现这里发布了类似的问题。但答案是基于一个字符串。但是,我在这里有不同的情况。我不是要删除字符串,而是要删除另一个名为 AwardYearSource 的对象。这个类有一个叫做 year 的 int 属性。所以我想根据年份删除重复项。即,如果不止一次提到 2010 年,我想删除该 AwardYearSource 对象。我怎样才能做到这一点?

4

7 回答 7

52

根据字段删除元素的最简单方法如下(保留顺序):

Map<Integer, AwardYearSource> map = new LinkedHashMap<>();
for (AwardYearSource ays : list) {
  map.put(ays.getYear(), ays);
}
list.clear();
list.addAll(map.values());
于 2012-04-16T15:36:23.260 回答
1

相当简单。尽管地图版本让我有些烦恼(并不是我怀疑它们会起作用,但不知何故,这似乎有点矫枉过正——尽管这个版本在这方面不一定更好)。
答案是功能性的,并且是线程安全的(假设AwardYearSource是不可变的)。

public static List<AwardYearSource> removeDuplicateYears(
                                          final Collection<AwardYearSource> awards) {
    final ArrayList<AwardYearSource> input = new ArrayList<AwardYearSource>(awards);
    // If there's only one element (or none), guaranteed unique.
    if (input.size() <= 1) {
        return input;
    }
    final HashSet<Integer> years = new HashSet<Integer>(input.size(), 1);
    final Iterator<AwardYearSource> iter = input.iterator();
    while(iter.hasNext()) {
        final AwardYearSource award = iter.next();
        final Integer year = award.getYear();
        if (years.contains(year)) {
            iter.remove();
        } else {
            years.add(year);
        }
    }
    return input;       

}
于 2012-04-16T15:57:14.197 回答
1

另一种方法是覆盖hashCode()equals(Object obj)为您的对象。由于它只有一个字段用于确定相等性,因此非常简单。就像是:

public boolean equals(Object obj) {
  if (obj == null || !(obj instanceof AwardYearSource)) {
    return false;
  }
  return (this.year == ((AwardYearSource)obj).year);
}
public int hashCode() {
  return this.year;
}

然后,您可以将所有对象粘贴到 aSet中以删除重复项:

Set<AwardYearSource> set = new Set<AwardYearSource>();

set.add(new AwardYearSource(2011));
set.add(new AwardYearSource(2012));
set.add(new AwardYearSource(2011));

for (AwardYearSource aws : set) {
  System.out.println(aws.year);
}
于 2012-04-16T15:44:39.033 回答
0

创建一个 HashMap 对象,其中 int 作为键类型,您的类作为值类型。然后遍历列表并将每个元素插入到地图中:

mymap.put(source.year, source);

然后从原始列表中删除所有元素并遍历地图并将每个元素插入到列表中。

于 2012-04-16T15:37:56.867 回答
0

您可以使用地图并以年份为键存储对象:

Map<Integer, AwardYearSource> map = new HashMap<Integer, AwardYearSource>();
map.put(someAwardYearSource1.getYear(), someAwardYearSource1);
map.put(someAwardYearSource2.getYear(), someAwardYearSource2);

etc.

最后,地图将按年份包含唯一值,您可以使用 values 方法调用它:

Collection<AwardYearSource> noDups = map.values();
于 2012-04-16T15:36:33.180 回答
0

如果您的 AwardYearSource 类覆盖了 equals 和 hashcode 方法(Eclipse 可以生成两者),那么您可以将它们添加到 Set。该集合将不包含任何重复项。

public class AwardYearSource
{
    private final int year;

    public AwardYearSource(int year)
    {
        this.year = year;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + year;
        return result;
    }

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

    @Override
    public String toString()
    {
        return String.valueOf(year);
    }


    public static void main(String[] args)
    {
        Set<AwardYearSource> set = new HashSet<AwardYearSource>();
        set.add(new AwardYearSource(2000));
        set.add(new AwardYearSource(2000));
        set.add(new AwardYearSource(2000));
        set.add(new AwardYearSource(2000));

        System.out.println(set);
    }
}

输出为 [2000]。套装中只有一件。

于 2012-04-16T15:47:54.167 回答
0
Set<Integer> set = new HashSet<>();
list.removeIf(i -> set.contains(i.getYear()) ? true : !set.add(i.getYear()));

这应该有帮助,在这种情况下,重复是根据某些属性(或属性的组合)来决定的,在这种情况下是年份。希望这可以帮助。

于 2017-10-17T18:52:24.777 回答