简体   繁体   中英

Counting the occurrence of objects in an ArrayList, using either Collections or my functions

I have an ArrayList of FlowerClass objects. Each of these FlowerClass objects has a name. I want to go through the ArrayList and count them. I want to display the amount of each. So if I have three FlowerClass objects named Rose, two named Daffodil, and one named Tulip...I want to display the following:

  • Found 3 Rose
  • Found 3 Daffodil
  • Found 3 Tulip

So far, I've gotten it to count correctly using two functions I made. The problem is that I iterate through the entire ArrayList...so it'll show me the results more than once. For example, if the user adds 3 Roses and 2 Daffodils...The output is like this:

  • Found 3 Roses
  • Found 3 Roses
  • Found 3 Roses
  • Found 2 Daffodils
  • Found 2 Daffodils

I know why the code does this but I don't know how to erase repeats of output. I also don't know how to implement Collections correctly. I've used Collections on an ArrayList of strings before...and it works. But this time I'd be using Collections on an ArrayList of Objects, and I want to check for the frequency of each specific name. Here is the main class:

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);
        }
    }
}

Here is the 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;
    }
}

If you look at my last function in the main class, you'll see that I commented out the way I was attempting to implement Collections.frequency. I also tried making a multidimensional array of Strings and storing the names of the flowers and also the number of flowers in the arrays. This was counting everything correctly but I wasn't sure how to display the names alongside the counts. It was getting very messy so I abandoned that attempt for now in favor of trying these other two options. If I can find a way to erase repeated lines of output (or if I can find a way to get Collections to work) then I won't need to tinker with the multidimensional array.

Any tips would be very much appreciated. Thank you for your time.

You could put your Flower(s) in a Set . But the easiest solution I can think of is to sort your flowers. So first, implement a Comparator<FlowerClass>

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

Then you can sort with Collections.sort(List, Comparator)

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

And then your for loop needs to be something like this (to stop searching for the same flower),

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.
  }
 }

Interesting code, but it doesn't work the way I would do it.

In this current case as you've done it, you would need to keep track of the flower names you have already encountered:

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);
        }
    }
}

What I would rather do is maintain a Map that keeps track of the counts of the flower types, and just obtain the numbers for the types from that:

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));
    }
}

That way, you could just display the flowers as the following:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM