Java系列-按人口、城市和州分类的州际印刷品

Java系列-按人口、城市和州分类的州际印刷品,java,sorting,collections,Java,Sorting,Collections,我正在处理一个在面试中遇到的问题 输入包含人口|城市|州|州际列表 输出需要先按人口降序排序,然后按城市和州的字母顺序排序,然后州际之间也需要按升序排序 样本输入: 27|Chicago|Illinois|I-94;I-90;I-88;I-57;I-55 83|New York|New York|I-78;I-95;I-87;I-80 15|Phoenix|Arizona|I-10;I-17;I-8 15|Philadelphia|Pennsylvania|I-95;I-76 83 New

我正在处理一个在面试中遇到的问题

输入包含人口|城市|州|州际列表

输出需要先按人口降序排序,然后按城市和州的字母顺序排序,然后州际之间也需要按升序排序

样本输入:

27|Chicago|Illinois|I-94;I-90;I-88;I-57;I-55
83|New York|New York|I-78;I-95;I-87;I-80
15|Phoenix|Arizona|I-10;I-17;I-8
15|Philadelphia|Pennsylvania|I-95;I-76
83

New York, New York
Interstates: I-78, I-80, I-87, I-95

27

Chicago, Illinois
Interstates: I-55, I-57, I-88, I-90, I-94

15

Philadelphia, Pennsylvania
Interstates: I-76, I-95

Phoenix, Arizona
Interstates: I-8, I-10, I-17
样本输出:

27|Chicago|Illinois|I-94;I-90;I-88;I-57;I-55
83|New York|New York|I-78;I-95;I-87;I-80
15|Phoenix|Arizona|I-10;I-17;I-8
15|Philadelphia|Pennsylvania|I-95;I-76
83

New York, New York
Interstates: I-78, I-80, I-87, I-95

27

Chicago, Illinois
Interstates: I-55, I-57, I-88, I-90, I-94

15

Philadelphia, Pennsylvania
Interstates: I-76, I-95

Phoenix, Arizona
Interstates: I-8, I-10, I-17
到目前为止,我的方法是这样的。我现在被困在if块中,在那里我添加了一条评论。我不确定我的方向是否正确。我在这里寻找一个采取正确方法的提示

Scanner sc = new Scanner(System.in);
String line;
List<String> al = new ArrayList<>();

//Outer map sorts reverse by population, inner map1 sorts by city, inner 
map2 sorts by state
Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
Map<String, Map<String, String>> innerMap1 = new TreeMap<>();
Map<String, String> innerMap2 = new TreeMap<>();

while(sc.hasNextLine() && (line = sc.nextLine()).length()!=0) {

  //Ignore if input contains this character
  if(line.contains("#")) {
    line = sc.nextLine();
  }

  al.add(line);
}

for(int i = 0; i < al.size(); i++) {

  int outerMapKey = Integer.parseInt(al.get(i).split("\\|")[0]);
  String innerMap1Key = al.get(i).split("\\|")[1];
  String innerMap2Key = al.get(i).split("\\|")[2];

  String value = al.get(i);

  outerMap.get(outerMapKey);

  if(outerMap.containsKey(outerMapKey)) {


    innerMap1 = outerMap.get(outerMapKey);
    /* Logic to put values in inner maps 
    This is going to get very convoluted, not sure if I have the 
    right approach
    */
  }
  else {
    innerMap1 = new TreeMap<>();
    innerMap2 = new TreeMap<>();
    innerMap2.put(innerMap2Key, value);
    innerMap1.put(innerMap1Key, innerMap2);
    outerMap.put(outerMapKey, innerMap1);
  }
  }
Scanner sc=新扫描仪(System.in);
弦线;
List al=新的ArrayList();
//外部地图按人口反向排序,内部地图1按城市排序,内部地图
map2按州分类
映射outerMap=新树映射
(Collections.reverseOrder());
Map innerMap1=新树映射();
Map innerMap2=新树映射();
而(sc.hasNextLine()&&(line=sc.nextLine()).length()!=0){
//如果输入包含此字符,则忽略
if(第行包含(“#”){
line=sc.nextLine();
}
al.添加(行);
}
对于(int i=0;i
谢谢你迄今为止的帮助。我在这里根据反馈发布我的代码(正在工作)。请看一看并建议如何改进

public static void main(String[] args) {

    Map<String, List<PopulationByCityState>> map = readAndProcessInput();
    printSortedOutput(map);

}


private static Map<String, List<PopulationByCityState>> readAndProcessInput() {

    Map<String, List<PopulationByCityState>> map = readInput();
    sortByPopulationCityAndState(map);
    return map;
}

private static Map<String, List<PopulationByCityState>> readInput() {
    System.out.println("Enter input:");
    Scanner sc = new Scanner(System.in);
    String line;
    Map<String, List<PopulationByCityState>> map = new TreeMap<>(Collections.reverseOrder());

    while (sc.hasNextLine() && (line = sc.nextLine()).length() != 0) {
        if (line.contains("#")) {
            line = sc.nextLine();
        }

        populateMap(line, map);

    }
    return map;
}

private static void populateMap(String line, Map<String, List<PopulationByCityState>> map) {

    String[] s = line.split("\\|");
    String[] is = s[3].split(";");
    String key = s[0];
    PopulationByCityState p = new PopulationByCityState();
    p.setPopulation(Long.parseLong(s[0]));
    p.setCity(s[1]);
    p.setState(s[2]);
    List<String> interstates = new ArrayList<>();


    for (String aString : is) {
        interstates.add(aString);
    }

    sortInterstates(interstates);
    p.setInterstates(interstates);

    if (map.containsKey(key)) {
        map.get(key).add(p);
    } else {
        List<PopulationByCityState> al = new ArrayList<>();
        al.add(p);
        map.put(key, al);
    }
}

private static void sortInterstates(List<String> interstates) {
    Collections.sort(interstates, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            int n1 = Integer.parseInt(o1.split("-")[1]);
            int n2 = Integer.parseInt(o2.split("-")[1]);

            return n1 - n2;
        }
    });
}

private static void sortByPopulationCityAndState(Map<String, List<PopulationByCityState>> map) {
    for (Map.Entry entry : map.entrySet()) {

        List<PopulationByCityState> list = (List<PopulationByCityState>) entry.getValue();


        Collections.sort(list, new Comparator<PopulationByCityState>() {
            @Override
            public int compare(PopulationByCityState o1, PopulationByCityState o2) {
                int c;
                c = (int) (o2.getPopulation() - o1.getPopulation());
                if (c == 0) {
                    c = o1.getCity().compareTo(o2.getCity());
                }
                if (c == 0) {
                    c = o1.getState().compareTo(o2.getState());
                }
                return c;
            }
        });
    }
}

private static void printSortedOutput(Map<String, List<PopulationByCityState>> map) {

    for (Map.Entry<String, List<PopulationByCityState>> entry : map.entrySet()) {
        System.out.println(entry.getKey());
        System.out.println();

        List<PopulationByCityState> list = entry.getValue();

        for (PopulationByCityState p : list) {
            System.out.println(p.getCity() + ", " + p.getState());
            List<String> interstates = p.getInterstates();
            System.out.print("Interstates: ");
            int s = 0;

            for (String is : interstates) {
                s++;
                System.out.print(is);
                if (s != interstates.size()) {
                    System.out.print(", ");
                }

            }
            System.out.println();
            System.out.println();
        }


    }
}
publicstaticvoidmain(字符串[]args){
Map Map=readAndProcessInput();
打印输出(地图);
}
私有静态映射readAndProcessInput(){
Map=readInput();
sortByPopulationCityAndState(地图);
返回图;
}
私有静态映射readInput(){
System.out.println(“输入:”);
扫描仪sc=新的扫描仪(System.in);
弦线;
Map Map=newtreemap(Collections.reverseOrder());
而(sc.hasNextLine()&&(line=sc.nextLine()).length()!=0){
if(第行包含(“#”){
line=sc.nextLine();
}
人口地图(线、地图);
}
返回图;
}
私有静态void populateMap(字符串行、映射){
字符串[]s=line.split(“\\\\”);
字符串[]为=s[3]。拆分(;);
字符串键=s[0];
PopulationByCityState p=新的PopulationByCityState();
p、 setPopulation(Long.parseLong(s[0]);
p、 设定城市(s[1]);
p、 设定状态(s[2]);
列表州际=新建ArrayList();
用于(字符串aString:is){
州际公路。添加(阿斯汀);
}
sortInterstates(州际);
p、 州际(州际);
if(地图容器(图例)){
map.get(key)、add(p);
}否则{
List al=新的ArrayList();
al.添加(p);
地图放置(键,al);
}
}
私人静态无效分类状态(列出州际){
Collections.sort(州际,新比较器(){
@凌驾
公共整数比较(字符串o1、字符串o2){
int n1=Integer.parseInt(o1.split(“-”[1]);
int n2=Integer.parseInt(o2.split(“-”[1]);
返回n1-n2;
}
});
}
私有静态无效sortByPopulationCityAndState(映射){
对于(Map.Entry:Map.entrySet()){
List=(List)entry.getValue();
Collections.sort(list,newcomparator(){
@凌驾
公共整数比较(按CityState o1填充,按CityState o2填充){
INTC;
c=(int)(o2.getPopulation()-o1.getPopulation());
如果(c==0){
c=o1.getCity().compareTo(o2.getCity());
}
如果(c==0){
c=o1.getState().compareTo(o2.getState());
}
返回c;
}
});
}
}
专用静态无效打印分拣输出(地图){
对于(Map.Entry:Map.entrySet()){
System.out.println(entry.getKey());
System.out.println();
List=entry.getValue();
for(按城市状态p:list填充){
System.out.println(p.getCity()+”,“+p.getState());
列出州际公路=p.getInterstates();
系统输出打印(“州际:”);
int s=0;
对于(字符串为:州际){
s++;
系统输出打印(is);
如果(s!=州际.size()){
系统输出打印(“,”);
}
}
System.out.println();
System.out.println();
}
}
}

您的方法依赖于过于复杂且没有意义的结构,还使用了一个比较器,该比较器只对地图的第一级进行排序:

Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
将它们的实例添加到
列表中
,并使用比较器,首先按人口降序排列,然后按城市和州的字母顺序排列。
州际
字段可以在外部元素排序期间独立或直接排序。
您可以在
PopulationForState
中提供排序方法,例如
sortinenerstates()
以升序对它们进行排序。

就个人而言,我会独立进行,以减少处理之间的耦合。

所以你可以写一些像:

List<PopulationForState> populationForStates = new ArrayList<>();
populationForStates.add(new PopulationForState(...));
populationForStates.add(new PopulationForState(...));

Collection.sort(populationForStates, Comparator.comparing(PopulationForState::population).reversed()
          .thenComparing(PopulationForState::getCity)
          .thenComparing(PopulationForState::getState);

populationForStates.stream()
                   .forEach(PopulationForState::sortInnerStates);
List populationForStates=new ArrayList();
添加(新的填充ForState(…);
添加(新的填充ForState(…);
Collection.sort(填充状态、比较
Collections.sort(populatisForStates, new Comparator<PopulationForState>(){
   public int compare(PopulationForState first, PopulationForState scnd) {
      int compare = first.population - scnd.population;
      if(compare != 0) return compare;
      compare = first.city.compareTo(scnd.city);
      if(compare != 0) return compare;
      return first.state.compareTo(scnd.state);
   }
});