对对象的数组列表进行排序,如果名称匹配则添加值

Sorting an arraylist of object, and adding values if the name is matching

我想对对象数组列表进行排序,如果状态相同,则添加 motorThefts 的值。我不擅长处理数组列表、比较等,因此不胜感激。 - 显示每个州(按字母顺序排列)的汽车盗窃总数。 示例输出:

各州与汽车盗窃

AK 1898

AL 9599

AR 5377

AZ 48322

我有一个 class StartUp.java 和 CityCrime 类型的 ArrayList

    public static ArrayList<CityCrime> crimes = new ArrayList<CityCrime>();

    /**
 * Reads the crime data for each city from file
 */
public static void readCrimeData() {
    
    File file = new File("crimeUSA.csv");

    FileReader fileReader;
    BufferedReader bufferedReader;
    String crimeInfo;
    String[] stats;

    try {
        fileReader = new FileReader(file);
        bufferedReader = new BufferedReader(fileReader);

        crimeInfo = bufferedReader.readLine();
        crimeInfo = bufferedReader.readLine();

        do {
            CityCrime crime = new CityCrime(); // Default constructor
            stats = crimeInfo.split(",");
            {
                if(stats[0] != null) {
                crime.setCity(stats[0]);
            }
            if(stats[1] != null) {
                crime.setState(stats[1]);
            }
            if(stats[2] != null) {
                if(Integer.parseInt(stats[2]) >=0) {
                    crime.setPopulation(Integer.parseInt(stats[2]));
                }
            }
            if(stats[3] != null) {
                if(Integer.parseInt(stats[3]) >=0) {
                    crime.setMurder(Integer.parseInt(stats[3]));
                }
            }
            
            if(stats[4] != null) {
                if(Integer.parseInt(stats[4]) >=0) {
                    crime.setRobbery(Integer.parseInt(stats[4]));
                }
            }
            
            if(stats[5] != null) {
                if(Integer.parseInt(stats[5]) >=0) {
                    crime.setAssault(Integer.parseInt(stats[5]));
                }
            }
                
            if(stats[6] != null) {
                if(Integer.parseInt(stats[6]) >=0) {
                    crime.setBurglary(Integer.parseInt(stats[6]));
                }
            }
            
            if(stats[7] != null) {
                if(Integer.parseInt(stats[7]) >=0) {
                    crime.setLarceny(Integer.parseInt(stats[7]));
                }
            }
            
            if(stats[8] != null) {
                if(Integer.parseInt(stats[8]) >=0) {
                    crime.setMotorTheft(Integer.parseInt(stats[8]));
                }
            }
            
        }
            crimes.add(crime);
            System.out.println(crime);

            crimeInfo = bufferedReader.readLine();

        } while (crimeInfo != null);

        fileReader.close();
        bufferedReader.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (NumberFormatException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
}

这些是我目前使用的方法。

    public static void carThefts() {
    Collections.sort(crimes, new Comparator<CityCrime>(){
        public int compare(CityCrime d1, CityCrime d2){
            return Integer.compare(d1.getMotorTheft(), d2.getMotorTheft());
        }
        
    });
}

public static void displayStateCarThefts() {
    int carTheft = 0;
    for(CityCrime crime : crimes) {
        if(crime.getState().equalsIgnoreCase(crime.getState())) {
            carTheft = carTheft + crime.getMotorTheft();
        }
        
        System.out.printf("%-20s %5s %10s\n", "State", ":" , crime.getState());
        System.out.printf("%-20s %5s %10d\n", "Motor Theft", ":" , carTheft);
    }

    

在我的 CityCrime.java 我有

    public class CityCrime {


//Instance variables

private String city;
private String state;
private int population;
private int murder;
private int robbery;
private int assault;
private int burglary;
private int larceny;
private int motorTheft;
public int totalCrimes;


public static void main(String[] args) {
    
}

public int getTotalCrimes() {
    return totalCrimes;
}

public int setTotalCrimes(int murder, int robbery, int assault, int burglary, int larceny, int motorTheft) {
    this.totalCrimes = murder + robbery + assault + burglary + larceny + motorTheft;
    return totalCrimes;
}

public String getCity() {
    return city;
}


public void setCity(String city) {
    this.city = city;
}

public String getState() {
    return state;
}


public void setState(String state) {
    if(state.equalsIgnoreCase("ALABAMA")) {
        this.state = "AL";
    }
    else if(state.equalsIgnoreCase("ALASKA")) {
        this.state = "AK";
    }

    //etc

public int getMurder() {
    return murder;
}


public void setMurder(int murder) {
    this.murder = murder;
}


public int getRobbery() {
    return robbery;
}


public void setRobbery(int robbery) {
    this.robbery = robbery;

}


public int getAssault() {
    return assault;
}


public void setAssault(int assault) {
    this.assault = assault;

}


public int getBurglary() {
    return burglary;
}


public void setBurglary(int burglary) {
    this.burglary = burglary;

}


public int getLarceny() {
    return larceny;
}


public void setLarceny(int larceny) {
    this.larceny = larceny;
}


public int getMotorTheft() {
    return motorTheft;
}


public void setMotorTheft(int motorTheft) {
    this.motorTheft = motorTheft;

}

public static void showAllMurderDetails() {

    for (CityCrime crime : StartApp.crimes) {
        System.out.println("Crime: City= " + crime.getCity() + ", Murder= " + crime.getMurder());
    }
    System.out.println();
}


public static int showAllViolentCrimes() {
    int total = 0;
    for(CityCrime crime : StartApp.crimes) {
        total=total+crime.getMurder();
        total=total+crime.getRobbery();
        total=total+crime.getAssault();
    }
    System.out.println("Total of violent crimes: " + total);
    return total;
    
}

public static int getPossessionCrimes() {
    int total=0;
    for (CityCrime crime : StartApp.crimes) {
        total = total + crime.getBurglary();
        total = total + crime.getLarceny();
        total = total + crime.getMotorTheft();
    }
    System.out.println("Total of possession crimes: " + total);
    return total;
}

}

我也走过这条路,但发现自己仍然卡住了 :

        public static void displayStateCarThefts() {
    Map<String, CityCrime> map = new HashMap<>();
    for(CityCrime c : crimes) {
        
        CityCrime crime = map.get(c.getState());
        if(crime != null) {
            crime.setMotorTheft(crime.getMotorTheft()+c.getMotorTheft());
        }
        else {
            map.put(c.getState(), c);
        }
    }
    System.out.println(map.values());
    //System.out.println(Arrays.asList(map.values().toArray()));    

}

非常感谢对此的任何帮助。谢谢

这是我的解决方案:

public static void displayStateCarThefts() {
        final var map = new HashMap<String, Integer>();
        for(var c : crimes) {
            final int previousValue = map.getOrDefault(c.getState(), 0); // If the key does not exist, return 0 as default value
            map.put(c.getState(), previousValue + c.getMotorTheft()); // Update the value on the Map
        }

        final var sortedKeys = new LinkedList<>(map.keySet()); // Create a new list of String with all keys inside
        sortedKeys.sort(Comparator.naturalOrder()); // Sort keys in natural order
        for(final var key: sortedKeys) // Iterate over keys
            System.out.println(key + " " + map.get(key));

}

我看到你使用 ArrayList,我建议你改用 LinkedList。 ArrayList 是使用 Java 数组的 List 的实现。访问特定元素(第 n 个元素)确实很好,但这种类型的列表在其他方面并不是最优的。事实上,如果你想添加一个元素并且这个内部数组已满,实现必须在内部创建新数组。
LinkedList 使用链表的原理。里面的每个对象都包裹在一个节点中,节点连接到前一个和下一个节点形成列表。这种类型的列表在访问第 n 个元素时并不是很有效,但是添加一个元素没有额外的成本(通过 add 函数)。
从迭代的角度来看,我认为两者在性能上是相似的。

Why not sort directly the Map?

因为Map是无序类型。所以如果没有顺序,我们就无法对地图进行排序。
如果您对代码有任何其他问题,请不要犹豫!