【问题标题】:Why is my loop not retrieving the last items?为什么我的循环没有检索到最后的项目?
【发布时间】:2018-10-15 20:22:33
【问题描述】:

我正在尝试实现一种方法来查看项目列表及其数量,而无需重复。我正在使用 ArrayList 执行此操作,它将保存我创建的 Item 类型的对象。问题出在循环中,我从原始列表的副本中删除重复项,因为它没有显示列表中的最后两个项目,我不知道如何修复它。这是代码。 Item 是一个很简单的对象,它包含(int identifier, int price, String name)

private ArrayList list;

public void print(ListOfItems storeList)
{
    list = storeList.getList();
    if ( list.size() == 0)
        System.out.println("Sorry! There are no available Items at the store at this moment.");
    /** I changed this section
    else
    {
        Object[] originalItems = list.toArray();
        ArrayList copy = storeList.getCopy(storeList.getList());
        Object[] copyItems = copy.toArray();
        System.out.println("Here is a list Of available items in this Store");
        System.out.println("Name\tIdentifier\tprice\tQuantity");

       //this loop is wrong
        for (int i = 0; i < originalItems.length-1; i++)
        {
            for (int j = i+1; j < originalItems.length; j++)
            {
                if (originalItems[i].equals(originalItems[j]) && copyItems[j] != null)
                {
                    copy.remove(originalItems[j]);
                }
            }
        }
        **/
        //Below is the write loop
        else
        {
        Object[] originalItems = list.toArray();
        ArrayList copy = new ArrayList(list.size());
        for (int i = 0; i < originalItems.length; i++)
        {
            Item item = (Item) originalItems[i];
            if (copy.contains(item) == false)
            {
                copy.add(item);
            }
        }

        Object[]cop = copy.toArray();
        for (int i = 0; i < cop.length; i++)
        {
            if (cop[i] != null)
            {
                Item item = (Item) copyItems[i];
                System.out.print(item.getName() + "\t");
                System.out.print(item.getIdentifier() + "\t\t");
                System.out.print(item.getPrice() + "\t");
                System.out.print(Methods.getOccurences(list, item));
                System.out.println();
            }
        }

        System.out.print("*****************************");
    }
}

这是 ListOfItems 的类

import java.util.ArrayList;
public class ListOfItems 
{
int numOfItemsInStore = 50;
private ArrayList list = new ArrayList(numOfItemsInStore);
public ListOfItems()
{
    Item item1 = new Item (111, 50, "Item1");
    list.add(item1);
    Item item2 = new Item (222, 99, "Item2");
    list.add(item2);
    Item item3 = new Item (333, 20, "Item3");
    list.add(item3);
    Item item4 = new Item (444, 199, "Item4");
    list.add(item4);
    Item item5 = new Item (555, 14, "Item5");
    list.add(item5);
    Item item6 = new Item (666, 40, "Item6");
    list.add(item6);
    list.add(item6);
    list.add(item6);
    list.add(item2);
    list.add(item3);
    list.add(item3);
    list.add(item3);
}

public ArrayList getList()
{
    return list;
}


public ArrayList getCopy(ArrayList listToCopy)
{
    ArrayList copy = new ArrayList(numOfItemsInStore);
    if (listToCopy.isEmpty())
        System.out.println("This list is Empty");
    else
    {

        Object[] listArray = listToCopy.toArray();
        for (int i = 0; i < listArray.length; i++)
        {
            Item item = (Item) listArray[i];
            copy.add(item);
        }
    }

    return copy;
}
}

这里是 Item 类

public class Item 
{
private int identifier;
private int price;
private String name;

public Item (int id, int price , String name)
{
    this.identifier = id;
    this.name = name;
    this.price = price;
}

public int getIdentifier()
{
    return identifier;
}

public int getPrice()
{
    return price;
}

public String getName()
{
    return name;
}
}

【问题讨论】:

  • 请将项目类添加到问题中
  • 另外,你真的不需要中间数组来删除重复项
  • 应该if (copyItems[i] != null)if (cop[i] != null)
  • 是的,我编辑了这个问题。谢谢你注意到它。关于中间,是因为我不想弄乱原始列表
  • 也不需要copyItems

标签: java arrays loops object arraylist


【解决方案1】:

好的,首先我建议使用 Set 来删除重复项...

public void print(ListOfItems storeList)
{
    // At this point make sure that "getCopy(ArrayList <Item> listToCopy)" creates a deep copy!
    ArrayList <Item> copyOfList = storeList.getCopy(storeList.getList());

    // For using this statement make sure that you override "equals" in the "Item" class!
    Set <Item> uniqueItems = new HashSet <Item> (copyOfList);

    for(Item item : uniqueItems)
    {
        // Code for usage of each single item
    }
}

...这只是一种可能的解决方案,但请确保您覆盖 equals 并且您的函数getCopy() 创建一个deep 副本!

感谢Coderino Javarino,当然你必须覆盖equalshashCode方法不是toString方法!

覆盖equals 方法的一个选项...

@Override public boolean equals(Object object)
{
    if(this == object)
    {
        return true;
    }

    if(object == null || getClass() != object.getClass())
    {
        return false;
    }

    Item item = (Item) object;

    return Objects.equals(this.name, item.name) &&
         this.identifier == item.identifier &&
         this.price == item.price;
}

这里还有一个创建深拷贝的选项...

public ArrayList getCopy(ArrayList <Item> listToCopy)
{
    if(null == listToCopy)
    {
        // Handle this option too
    }

    ArrayList <Item> copy = new ArrayList(listToCopy.size());

    for(Item item : listToCopy)
    {
        // It is important that your class "Item" contains a copy constructor
        copy.add(new Item(item));
    }

    return copy;
}

【讨论】:

  • 谢谢。我现在看看 hashCode :) 我还在学习它
  • @RedEyez 听起来不错,但hashCode 本身并不能解决您的问题...您必须覆盖equals 方法,建议也覆盖hashCode 方法,但这不是不是解决它的部分
【解决方案2】:

根据您的代码,我猜第 6 项和第 3 项未在您的最终警察名单中。因为删除操作不正确。

在开始for循环时,3个变量的初始状态是:

  • 原始物品:[1,2,3,4,5,6,6,6,2,3,3,3]
  • 复制:[1,2,3,4,5,6,6,6,2,3,3,3]
  • copyItems:[1,2,3,4,5,6,6,6,2,3,3,3]

外部for循环完成第6轮(i=5)后上述3个变量的状态:

  • 原始物品:[1,2,3,4,5,6,6,6,2,3,3,3]
  • 副本:[1,2,3,4,5,6,2,3,3,3]
  • copyItems:[1,2,3,4,5,6,6,6,2,3,3,3]

不幸的是,当 i=6 和 j=7 时,我们发现“第 6 项”再次重复,复制列表将其删除。

我们完全能够解释为什么“第 3 项”会以同样的想法失败。它发生在 i=10, j=11 时。

以及如何解决它?如果还想用2个for循环,可以实现如下策略:

init copy list is empty
init originalitem as copy of your list
for item in originalItem
   isExist = false
   for copy list
       if item in copy
           isExist = true
           break
   if isExist = false
       copy add item 

但是,有很多方法可以有效地删除列表中的重复元素,而不是使用 2 个 for 循环策略。

【讨论】:

  • 感谢您的建议,我重写了循环。把答案放在上面。
【解决方案3】:
    else
    {
        Object[] originalItems = list.toArray();
        ArrayList copy = new ArrayList(list.size());
        for (int i = 0; i < originalItems.length; i++)
        {
            Item item = (Item) originalItems[i];
            if (copy.contains(item) == false)
            {
                copy.add(item);
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-11
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    相关资源
    最近更新 更多