Java 是否删除属于同一组的数组元素,只保留组中的1个?

Java 是否删除属于同一组的数组元素,只保留组中的1个?,java,arrays,Java,Arrays,我有一个数组myArray[]对象MyThing,其中包含X个元素。我需要删除属于同一组的元素,但每个组只留下一个代表 MyThing类有一个字段groupId public class MyThing { private int groupId; //...other fields public int getGroupId(){return groupId;} //getter and setter } 因此,我必须比较数组元素(myArray[x].getGroupI

我有一个数组
myArray[]
对象
MyThing
,其中包含X个元素。我需要删除属于同一组的元素,但每个组只留下一个代表

MyThing
类有一个字段
groupId

public class MyThing {

  private int groupId;
  //...other fields

  public int getGroupId(){return groupId;}
  //getter and setter
}
因此,我必须比较数组元素(
myArray[x].getGroupId()
)的
groupId
整数值,并删除除数组中第一个这样的元素之外属于同一组的所有元素

通过这种方式,我将获得一个只有1个来自同一组的唯一元素的数组。例如,如果我有一个净化后
a.getGroupId()=1,b.getGroupId()=2,c.getGroupId()=1
的数组,该数组将只包含
{a,b}
,并且
c
将被删除,因为它与
a
属于同一组

因为这是自定义对象,所以无法使用
Set

有什么想法吗


请让我知道,如果我解释清楚,因为它有点混乱

为什么不试试(这里是半伪代码):

List uniqGroups=new ArrayList();
for(int i=0;i
由于您只需要通过groupId来区分对象,您可以重写类中的hashCode()equals()方法:

class MyThing {
    private int groupId;
    public int getGroupId(){return groupId;}

    // new code to add...
    @Override
    public int hashCode() {
        return groupId;
    }
    @Override
    public boolean equals(Object o) {
        return (o instanceof MyThing
             && (groupId == ((MyThing)o).groupId));
    }
}
然后,使用HashSet类删除myArray中具有重复groupId的虚构对象:

myArray = new HashSet<MyThing>(Arrays.asList(myArray)).toArray(new MyThing[0]);
myArray=newhashset(Arrays.asList(myArray)).toArray(newmything[0]);

使用一个
树集和一个自定义的
比较器
类来检查对象,并将同一组中的两个对象视为相等

算法代码:

Create TreeSet
Add all array elements to TreeSet
Convert TreeSet back to array

对于示例实现:

按定义设置的集合不包含任何重复项。集合通过使用objects equals()/compareTo(..)方法或使用比较器来确定两个项是否相同。如果您只希望集合中的项目是唯一的,那么实现Compariable接口并重写equals()就是您想要做的事情。但在您的情况下,您只对独特组中的对象感兴趣,因此最好为该场合创建一个自定义比较器,然后将其提供给集合,告诉集合使用它,而不是“自然排序”

Set myThings=新树集(新比较器(){
@凌驾
公共整数比较(神话o1,神话o2)
{
返回o1.getGroupId()-o2.getGroupId();
}
}); 
addAll(Arrays.asList(myArray));
创建集合后,使用便利方法addAll(..)将整个数组添加到集合中


(比较器如何对对象进行排序完全取决于您的决定。)

您可以在数组中循环,并使用映射来跟踪哪些ID已经出现。然后,如果一个已添加到集合中,请将其从阵列中删除:

Set<Integer> uniqueIDs = new HashSet<Integer>();

for(MyThing thing : MyThings){
    int groupID = thing.getGroupId();

    if(!uniqueIDs.add(groupID)){
        // DUPLICATE, REMOVE IT
    }
}
Set uniqueid=new HashSet();
对于(虚构的事物:虚构){
int groupID=thing.getGroupId();
如果(!uniqueid.add(groupID)){
//复制,删除它
}
}

只需重写Martin的解决方案,因为比较器已损坏,它可能会溢出

Set<MyThing> myThings = new TreeSet<>(new Comparator<MyThing>() {
  @Override
  public int compare(MyThing  o1, MyThing  o2) {
    return Integer.compare(o1.getGroupId(), o2.getGroupId()); 
  }
}); 
myThings.addAll(Arrays.asList(myArray));
Set myThings=新树集(新比较器(){
@凌驾
公共整数比较(神话o1,神话o2){
返回整数.compare(o1.getGroupId(),o2.getGroupId());
}
}); 
addAll(Arrays.asList(myArray));

您仍然可以使用仅存储组ID的集合,并使用该集合消除重复项。您可以使用一个映射,其中键是您的组ID,值是该组中的第一个数组元素。然后可以对映射键进行简单检查。使用
Set
as
LinkedHashSet
可以在一行中完成所有这一切;)
Set obj=newlinkedhashset(Arrays.asList(myArray))。有了它,你甚至可以保留物品的顺序,如果它像我的情况一样重要的话。天哪,这很有效。比詹姆斯的解决方案还要快。你能在这里编辑回复并解释逻辑吗。我以前从未使用过
TreeSet
Comparator
。@sandalone TreeSet是一个依赖于顺序的内置集合。由于正常的Set接口只关心相等而不关心顺序,所以TreeSet将
比较器
作为构造函数参数,在插入过程中使用它而不是
equals()
/
hashcode()
。我已经知道了。与使用
LinkedHasSet
保持秩序相同。我被重写的方法
compare
弄糊涂了,该方法创建了两个
MyThing
对象,并减去了其字段的值(在我的例子中是组id)。为什么?这样做的目的是什么?它使用您提供的方法(比较(神话a,神话b))来确定添加到它的对象的顺序/一致性。当to对象被确定为“相等”时,您提供的方法必须返回0。谢谢。检查@Martin的解决方案。如此优雅和快速,只需注意TreeSet已订购。不确定列表的整体顺序是否重要。是的,这里的顺序很重要。
Set<Integer> uniqueIDs = new HashSet<Integer>();

for(MyThing thing : MyThings){
    int groupID = thing.getGroupId();

    if(!uniqueIDs.add(groupID)){
        // DUPLICATE, REMOVE IT
    }
}
Set<MyThing> myThings = new TreeSet<>(new Comparator<MyThing>() {
  @Override
  public int compare(MyThing  o1, MyThing  o2) {
    return Integer.compare(o1.getGroupId(), o2.getGroupId()); 
  }
}); 
myThings.addAll(Arrays.asList(myArray));