Подсчет вхождения объектов в ArrayList с использованием коллекций или моих функций
У меня есть ArrayList объектов FlowerClass. Каждый из этих объектов FlowerClass имеет имя. Я хочу пройти через ArrayList и посчитать их. Я хочу отобразить сумму каждого. Поэтому, если у меня есть три объекта FlowerClass с именем Rose, два с именем Daffodil и один с именем Tulip... Я хочу отобразить следующее:
- Найдено 3 розы
- Найдено 3 нарцисса
- Найдено 3 тюльпана
До сих пор я правильно рассчитывал, используя две сделанные мной функции. Проблема в том, что я перебираю весь ArrayList... так что он покажет мне результаты более одного раза. Например, если пользователь добавляет 3 розы и 2 нарцисса... Вывод будет таким:
- Найдено 3 розы
- Найдено 3 розы
- Найдено 3 розы
- Найдено 2 нарцисса
- Найдено 2 нарцисса
Я знаю, почему код делает это, но я не знаю, как стереть повторы вывода. Я также не знаю, как правильно реализовать Коллекции. Я использовал Collections в ArrayList строк раньше... и это работает. Но на этот раз я буду использовать Коллекции в 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. Я также попытался создать многомерный массив строк и сохранить названия цветов, а также количество цветов в массивах. Это считало все правильно, но я не был уверен, как отображать имена вместе с подсчетами. Это становилось очень грязным, поэтому я отказался от этой попытки, чтобы попробовать эти два других варианта. Если я смогу найти способ стереть повторяющиеся строки вывода (или если я смогу найти способ заставить Коллекции работать), мне не нужно будет возиться с многомерным массивом.
Любые советы будут очень цениться. Спасибо за ваше время.
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);
}
}
Вы можете положить свой цветок (ы) в Set
, Но самое простое решение, которое я могу придумать, это отсортировать цветы. Итак, во-первых, реализовать Comparator<FlowerClass>
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.
}
}