【问题标题】:Counting the occurrence of objects in an ArrayList, using either Collections or my functions使用集合或我的函数计算 ArrayList 中对象的出现次数
【发布时间】:2014-08-11 19:58:36
【问题描述】:

我有一个 FlowerClass 对象的 ArrayList。这些 FlowerClass 对象中的每一个都有一个名称。我想通过 ArrayList 并计算它们。我想显示每个的数量。因此,如果我有三个名为 Rose 的 FlowerClass 对象、两个名为 Daffodil 和一个名为 Tulip...我想显示以下内容:

  • 找到 3 朵玫瑰
  • 找到 3 朵水仙花
  • 找到 3 朵郁金香

到目前为止,我已经使用我制作的两个函数正确计算了它。问题是我遍历整个 ArrayList ......所以它会不止一次地向我显示结果。例如,如果用户添加了 3 朵玫瑰和 2 朵水仙花……输出是这样的:

  • 找到 3 朵玫瑰
  • 找到 3 朵玫瑰
  • 找到 3 朵玫瑰
  • 找到 2 朵水仙花
  • 找到 2 朵水仙花

我知道代码为什么会这样,但我不知道如何删除重复的输出。我也不知道如何正确实现集合。我之前在字符串的 ArrayList 上使用过 Collections ......并且它有效。但是这次我将在对象的 ArrayList 上使用集合,并且我想检查每个特定名称的频率。这是主要的类:

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;

public class MainClass {

    static ArrayList<FlowerClass> flowerPack = new ArrayList<FlowerClass>();


    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while(true){
            System.out.println("1. Add flower to flowerpack.");
            System.out.println("2. Remove flower from the flowerpack.");
            System.out.println("3. Search for a flower in the flowerpack."); 
            System.out.println("4. Display the flowers in the flowerpack.");
            System.out.println("5. Exit the program.");

            int userChoice = input.nextInt();

            switch(userChoice){
            case 1:
                addFlower();
                break;
            case 2:
                searchFlower();
                break;
            case 3:
                displayFlowers();
                break;
            case 4:
                    System.out.println("Goodbye!");
                System.exit(0);
            }
        }
    }

    public static void addFlower(){
        if (FlowerClass.numberFlowers() == 25){
            System.out.println("There are 25 flowers in the flowerpack. Remove at least one in order to add more.");
            return;
        }
        Scanner input = new Scanner(System.in);
        System.out.println("What is the flower's name?");
        String desiredName = input.nextLine();
        System.out.println("What is the flower's color?");
        String desiredColor = input.nextLine();
        System.out.println("How many thorns does it have?");
        Scanner input2 = new Scanner(System.in);
        int desiredThorns = input2.nextInt();
        System.out.println("What does it smell like?");
        String desiredSmell = input.nextLine();
        flowerPack.add(new FlowerClass(desiredName, desiredColor, desiredThorns, desiredSmell));
    }

    public static void searchFlower(){
        System.out.println("Enter the flower you want to search for.");
        Scanner input = new Scanner(System.in);
        String userChoice = input.nextLine();
        int occurrences  = 0;

        for (FlowerClass flower: flowerPack){
            String name = flower.getName();
            if (userChoice.equals(name)){
                occurrences++;
            }

            else if(occurrences == 0){
                System.out.println("Match not found.");
                return;
            }
        }

        System.out.println("Found " + occurrences + " " + userChoice);
    }

    public static void searchFlower(String desiredFlower){
        int occurrences = 0;

        String userChoice = desiredFlower;
        for (FlowerClass flower: flowerPack){
            String name = flower.getName();
            if (userChoice.equals(name)){
            occurrences++;
            }
        }

        System.out.println("Found " + occurrences + " " + userChoice);
    }

    public static void displayFlowers(){
        int repeats = 0;

        /*for (FlowerClass flower: flowerPack){
            System.out.println(flower.getName());
        }
        System.out.println("Number of flowers in pack: " + FlowerClass.numberFlowers());*/

            //int occurrences = Collections.frequency(flowerPack, name);
            //System.out.println(name + ": " + occurrences);
        for (FlowerClass flower: flowerPack){
            String name = flower.getName();
            searchFlower(name);
        }
    }
}

这是 FlowerClass:

public class FlowerClass {

    public static int numberOfFlowers = 0;
    public String flowerName = null;
    public String flowerColor = null;
    public int numberThorns = 0;
    public String flowerSmell = null;

    FlowerClass(){

    }

    FlowerClass(String desiredName, String desiredColor, int desiredThorns, String desiredSmell){
        flowerName = desiredName;
            flowerColor = desiredColor;
        numberThorns = desiredThorns;
        flowerSmell = desiredSmell;
        numberOfFlowers++;
    }

    public void setName(String desiredName){
        flowerName = desiredName;

    }

    public String getName(){
        return flowerName;
    }

    public static int numberFlowers(){
        return numberOfFlowers;
    }
}

如果您查看我在主类中的最后一个函数,您会发现我注释掉了我尝试实现 Collections.frequency 的方式。我还尝试制作一个多维字符串数组并存储花的名称以及数组中的花数。这是正确计算所有内容,但我不确定如何在计数旁边显示名称。它变得非常混乱,所以我暂时放弃了这种尝试,转而尝试其他两种选择。如果我能找到一种方法来擦除重复的输出行(或者如果我能找到一种让 Collections 工作的方法),那么我就不需要修补多维数组了。

任何提示将不胜感激。感谢您的时间。

【问题讨论】:

  • 使用迭代器迭代数组列表 Iterator itr = al.iterator(); while(itr.hasNext())

标签: java object collections arraylist find-occurrences


【解决方案1】:

您可以将您的花放在Set 中。但我能想到的最简单的解决方案是对你的花进行分类。所以首先,实现一个Comparator&lt;FlowerClass&gt;

public static class FlowerComparator implements Comparator<FlowerClass> {
  @Override
  public int compare(FlowerClass o1, FlowerClass o2) {
    return o1.getName().compareTo(o2.getName());
  }
}

然后就可以用Collections.sort(List, Comparator)排序了

FlowerComparator flowerComparator = new FlowerComparator();
Collections.sort(flowerPack, flowerComparator);

然后你的for 循环需要是这样的(停止搜索相同的花),

String lastName = null;
for (int i = 0; i < flowerPack.size(); i++){
  FlowerClass flower = flowerPack.get(i);
  String name = flower.getName();
  if (lastName == null || !lastName.equals(name)) {
    lastName = name;
    searchFlower(name); // or return the number found, and then add that count to i.
  }
 }

【讨论】:

  • 完美。您有比较器的首选资源吗?我想了解更多关于他们的信息。您的解决方案完美运行。我创建了一个名为 FlowerComparator 的新类。它并没有让我让它保持静态。必须消除静电。所以标题是: public class FlowerComparator implements Comparator
【解决方案2】:

有趣的代码,但它不像我那样工作。

在当前的情况下,您需要跟踪您已经遇到的花名:

public static void displayFlowers(){
    //int repeats = 0;
    List<String> displayedFlowerTypes = new ArrayList<String>();
    for (FlowerClass flower: flowerPack){
        String name = flower.getName();
        if(!displayedFlowerTypes.contains(name))
        {
            displayedFlowerTypes.add(name);
            searchFlower(name);
        }
    }
}

我宁愿做的是维护一个跟踪花卉类型数量的地图,并从中获取类型的数字:

public class MainClass {

static List<FlowerClass> flowerPack = new ArrayList<FlowerClass>();
static Map<String, Integer> flowerCount = new HashMap<String, Integer>();

public static void addFlower() {
    if (FlowerClass.numberFlowers() == 25) {
        System.out.println("There are 25 flowers in the flowerpack. Remove at least one in order to add more.");
        return;
    }
    Scanner input = new Scanner(System.in);
    System.out.println("What is the flower's name?");
    String desiredName = input.nextLine();
    System.out.println("What is the flower's color?");
    String desiredColor = input.nextLine();
    System.out.println("How many thorns does it have?");
    Scanner input2 = new Scanner(System.in);
    int desiredThorns = input2.nextInt();
    System.out.println("What does it smell like?");
    String desiredSmell = input.nextLine();
    flowerPack.add(new FlowerClass(desiredName, desiredColor, desiredThorns, desiredSmell));
    if(!flowerCount.containsKey(desiredName))
    {
        flowerCount.put(desiredName, 1);
    }
    else
    {
        int currentCount = flowerCount.get(desiredName);
        flowerCount.put(desiredName, currentCount+1));
    }
}

这样,您可以将花朵显示如下:

    public static void displayFlowers() {
        for (String name : flowerCount.keySet()) {
            //searchFlower(name);
            System.out.println("Found " + flowerCount.get(name) + " " + name);
        }
    }

【讨论】:

  • 感谢您的帮助。不幸的是,我还没有准备好使用地图。我正在为一个中期项目练习(这不是中期项目),我相信我们可以使用数组和数组列表,所以我正在为此做准备。不过,我真的很喜欢你写的新的 ArrayList。这正是我所需要的,我可以说它已经工作了。完美的答案。我也喜欢其他人的回答,但这不需要其他课程,它使用的是我已经练习过的 ArrayLists。会尝试实现这一点。
  • 我能够成功实现它。我喜欢它。我不需要对任何东西进行分类,我可以移除和添加更多的花,到目前为止没有任何问题。这真的很棒。谢谢你的帮助。我也会研究 Map 解决方案。就速度而言,这两种解决方案是否明显更好?我不需要担心速度,但我很好奇在搜索特定内容时 Map 是否比 ArrayList 快。
  • 很高兴它按您的预期工作! :) 我喜欢排序解决方案,因为它很有意义,但是当“无错误”和直观解决方案的速度是必须的时,我不想在中期测试中写在纸上。我的两种方法之间的主要区别在于,对于所有类型的显示,List 版本需要遍历整个 List 的次数与花卉类型一样多,以获得 O(N) 的计数;但是 Map 已经将信息存储在给定键的值中,因此可以通过 O(1) 的单个操作而不是列表迭代来完成
  • 所以从技术上讲,如果 List 中有很多花,那么 List 方法会比 Map 解决方案慢得多(获取每种类型的花的数量)。但是有 25 朵花,差别就不是那么大了。
猜你喜欢
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
相关资源
最近更新 更多