从仅给定一个属性的 ArrayList 中删除对象

Posted

技术标签:

【中文标题】从仅给定一个属性的 ArrayList 中删除对象【英文标题】:Remove an object from an ArrayList given only one attribute 【发布时间】:2015-05-23 02:36:44 【问题描述】:

我有一个项的 ArrayList,我希望能够通过仅输入一个项属性(例如其编号 (int ItemNumber))从列表中删除一项。当我检查商品数量时,我也想这样做。

这些是我的equals()contains() 方法,我需要在此处进行任何更改吗?

public boolean contains(T anEntry) 
    boolean found = false;
    for (int index = 0; !found && (index < numberOfEntries); index++) 
    if (anEntry.equals(list[index])) 
        found = true;
    //end for
    return found;
 // end contains

public boolean equals(Object object)
    Item item = (Item) object;
    if (itemNo == item.itemNo)
        return true;
    return false;

【问题讨论】:

我想你想看看使用地图而不是列表 抱歉,我什至不知道该代码的来源。是包含该项目的类(在列表中)吗?那为什么要覆盖equals呢?还是您将来自不同类的两个方法放在同一个代码块中?令人困惑... 【参考方案1】:

您要删除特定索引处的对象吗?我不完全确定您所说的“数字字段”是什么意思。如果是,跳转到方法:remove(int):

http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove%28int%29

编辑:如果您想在数组列表中查找/调整对象的字段,您可以这样做(我自己的一段代码):

public boolean studentHasISBN(ArrayList<Student> st, String s)
    for(Student j : st) 
        if(s.equals(j.getRentedBookISBN()))
            return true;
    
    return false;

您所要做的就是遍历列表,然后搜索您要查找的字段。然后使用 remove(int) 方法。

【讨论】:

我有一个具有以下属性(ItemNumber、ItemName、ItemPrice、Quantity)的类 Items 我想仅使用 ItemNumber 属性删除 who Item,这怎么可能?【参考方案2】:

只需在Java中使用ArrayListsremove函数即可:

theNameOfYourArrayList.remove(ItemNumber);

删除索引为(int ItemNumber)的元素

检查项目编号为(int ItemNumber) 的元素是否存在于您的ArrayList(假设称为theNameOfYourArrayList)中:

theNameOfYourArrayList.get(ItemNumber);

【讨论】:

我如何检查这个 ItemNumber 是否存在于我的列表中?【参考方案3】:

如果您更改类Item equals()compareTo() 方法,以便它们只检查一个对象字段,例如quantity,这可能会导致应用程序的其他部分出现奇怪的行为。例如,具有不同itemNoitemNameitemPrice 但数量相同的两个项目可以被视为相等。此外,如果不每次都更改equals() 代码,您将无法更改比较属性。

另外,创建自定义 contains() 方法没有意义,因为它属于 ArrayList 类,而不是 Item

如果你可以使用 Java 8,一个干净的方法是使用新的CollectionremoveIf 方法:

假设您有一个具有numname 属性的Item 类:

class Item 
    final int num;
    final String name;

    Item(int num, String name) 
        this.num = num;
        this.name = name;
    

给定一个名为 itemsList&lt;Item&gt; 和一个名为 numberint 变量,表示您要删除的项目的编号,您可以简单地这样做:

items.removeIf(item -> item.num == number);

如果您无法使用 Java 8,您可以通过使用自定义比较器、二分搜索和虚拟对象来实现。

您可以为需要查找的每个属性创建一个自定义比较器。 num 的比较器如下所示:

class ItemNumComparator implements Comparator<Item> 
    @Override
    public int compare(Item a, Item b) 
        return (a.num < b.num) ? -1 : ((a.num == b.num) ? 0 : 1);
    

然后您可以使用比较器对列表中的所需元素进行排序和搜索:

public static void main(String[] args) 
    List<Item> items = new ArrayList<>();
    items.add(new Item(2, "ball"));
    items.add(new Item(5, "cow"));
    items.add(new Item(3, "gum"));

    Comparator<Item> itemNumComparator = new ItemNumComparator();
    Collections.sort(items, itemNumComparator);

    // Pass a dummy object containing only the relevant attribute to be searched
    int index = Collections.binarySearch(items, new Item(5, ""), itemNumComparator);
    Item removedItem = null;
    // binarySearch will return -1 if it does not find the element.
    if (index > -1) 
        // This will remove the element, Item(5, "cow") in this case, from the list
        removedItem = items.remove(index);
    
    System.out.println(removedItem);

例如,要搜索名称等其他字段,您需要创建一个名称比较器并使用它对列表进行排序和运行二进制搜索。

请注意,此解决方案虽然有一些缺点。除非您完全确定列表自上次排序后没有更改,否则您必须在运行 binarySearch() 方法之前对其重新排序。否则,它可能无法找到正确的元素。排序复杂度为O(nlogn),因此根据列表的大小,多次运行它可能会变得非常昂贵。

【讨论】:

它不起作用:(我认为单独的类有问题我可以以某种方式实现一个名为 CompareTo 的方法,它可以与上面提到的 contains() 和 equals() 方法一起使用吗? 您遇到了什么问题?仅检查一个属性的 compareTo 和 equals 方法可能会在使用 Item 对象的代码的其他部分中导致奇怪的行为。 什么奇怪的行为? compareTo 方法的想法是什么?我会试试看。有了这个,我的类本身就有问题我收到这个错误:“方法 compare(int, int) 未定义整数类型” 问题是您可能使用的是 Java 6,它没有 Integer.compare() 方法。我更新了答案,请立即尝试使用 compare() 方法。我还解释了将 equals() 更改为仅检查一个属性的问题。 compareTo() 方法与上面的 compare() 方法几乎相同,但它会在 Item 类中实现,并且只接受一个 Item 对象作为参数。 这可行,但我认为我不应该为此实现一个单独的类。我必须在适用于任何类型的 ArrayList 类中实现我的所有方法,在我的情况是项目。这就是我尝试实现 compareTo 的原因【参考方案4】:

我将假设“数字字段”是指使用 Integer 数据类型调用 ArrayList。对于您的问题,我有几种不同的解决方案:

    ArrayLists,假设 ArrayList 是ArrayList&lt;Integer&gt; numList = new ArrayList&lt;Integer&gt;();,您可以简单地编写一个方法来搜索“numList”并删除该数字所在的索引。问题是,在 ArrayLists 中包含和查找可能会很慢。

    public void deleteNumField(int field) // this will stop any error if field isn't actually in numList // and it will remove the first index of field in the ArrayList if(numList.contains(field)) numList.remove(numList.find(field));

    HashSets,HashSets 是一种方便的数据类型,类似于 ArrayList,只是它的数据是它的“索引”(排序)。我不会深入讨论它们是如何工作的,但我会说在它们中搜索被认为是 O(1)。这将使您的删除变得非常容易和快速。注意:HashSet 假设没有重复的数字,如果有则使用 HashMap。

    HashSet<Integer> numList = new HashSet<Integer>(); public void deleteNumField(int field) // this will stop errors from attempting to remove a // non-existant element, and remove it if it exists. if(numList.contains(field)) numList.remove(field);


有关 HashMaps、HashSets 和 ArrayLists 的更多信息,请参阅: http://docs.oracle.com/javase/8/docs/api/

【讨论】:

以上是关于从仅给定一个属性的 ArrayList 中删除对象的主要内容,如果未能解决你的问题,请参考以下文章

检查 ArrayList 是不是包含给定对象

如何从 ArrayList 中正确删除对象?

从 ArrayList 中删除给定长度的字符串?

使用正则表达式从 JSON 中删除具有给定属性的对象

java如何对ArrayList中对象按照该对象某属性排序

根据自定义对象属性从数组列表中删除元素