用Java在像Objects这样的元组上分组

时间:2019-06-30 02:56:14

标签: java java-8

我有一个唯一的位置对象集,其数据如

location 1: "USA", "AZ", "Phoenix"
location 2: "USA", "AZ", "Scottsdale"
location 3: "USA", "AZ", "Peoria"

Front end needs following json structure to render UI:

"USA"-> [{"AZ" -> ["Phoenix", "Scottsdale","Peoria"]},
         {"MD" -> ["Baltimore", "Gaithersburg","OwingsMills"]}
        ]

Location.java的Java POJO

我编写了几行代码,以循环访问位置集,并使用FacetsGeo对象构造包含状态对象集的国家对象,其中包含状态对象的集包含城市对象的集,并从此数据模型中生成json。

我在想,可能有更好的方法:可能使用Java 8 Streaming API。

正如我在上面所说的那样,任何帮助表示赞赏的是示例数据如何构建平坦的位置。

public class Location {

        private final String country;
        private final String state;
        private final String city;

        public Location(final String country, final String state, final 
                String city) {
           this.country = country;
           this.state = state;
           this.city = city;
        }

        public String getCountry() {
            return country;
        }
        public String getState() {
            return state;
        }
        public String getCity() {
            return city;
        }

        @Override
        public boolean equals(Object thatLocation) {

            if (thatLocation == this) return true;
            if (!(thatLocationCriteria instanceof Location)) {
                return false;
            }
            Location location = (Location) thatLocation;

            return Objects.equals(this.country, location.country) && 
             Objects.equals(this.state, location.state) && 
             Objects.equals(this.city, location.city);
        }

        @Override
        public int hashCode() {
            return Objects.hash(this.country, this.state, this.city);
        }
    }

FacetsGeo.java

public class FacetsGeo {
    private String label;

    private String value;

    private String type;

    private String subtype;

    private List<FacetsGeo> childFacetsGeo;

 }

我试图在前端数据结构上方生成的内容:

`       List<FacetsGeo> facetsList = new ArrayList<FacetsGeo>();

    Optional<locations> locationsOptional = Optional.ofNullable(locations);
    if(locationsOptional.isPresent()) {
        //locations 
        for (final Location location : locationsOptional.get().getLocations()) {
            FacetsGeo facetCountry = new FacetsGeo();

            if(location.getCountry() != null 
                    && location.getCountry().equalsIgnoreCase("United States") 
                    && location.getState() != null) {
                boolean countryExists = false;
                for(FacetsGeo facetGeo: facetsList) {
                    if(facetGeo.getType() != null && facetGeo.getSubtype() != null 
                            && facetGeo.getType().equalsIgnoreCase("location")
                            && facetGeo.getSubtype().equalsIgnoreCase("country")
                            && facetGeo.getValue().equalsIgnoreCase(location.getCountry())) {
                        facetCountry = facetGeo;

                        if(facetCountry.getSubCriteria() == null) {
                            facetCountry.setSubCriteria(new ArrayList<FacetsGeo>());
                        }
                        countryExists = true;
                        break;
                    }

                }

                if(!countryExists) {
                    facetCountry.setLabel(location.getCountry());
                    facetCountry.setValue(location.getCountry());
                    facetCountry.setType("location");
                    facetCountry.setSubtype("country");

                    FacetsGeo subcriteriaState = new FacetsGeo();
                    subcriteriaState.setLabel(location.getState());
                    subcriteriaState.setValue(location.getState());
                    subcriteriaState.setType("location");
                    subcriteriaState.setSubtype("state");

                    FacetsGeo subcriteria = new FacetsGeo();
                    subcriteria.setLabel(location.getCity());
                    subcriteria.setValue(location.getCity());
                    subcriteria.setType("location");
                    subcriteria.setSubtype("city");

                    subcriteriaState.setSubCriteria(new ArrayList<FacetsGeo>());
                    subcriteriaState.getSubCriteria().add(subcriteria);

                    facetCountry.setSubCriteria(new ArrayList<FacetsGeo>());
                    facetCountry.getSubCriteria().add(subcriteriaState);

                    searchBarFacetsList.add(searchBarFacetCountry);
                } else {
                    FacetsGeo subcriteriaCity = new FacetsGeo();
                    subcriteriaCity.setLabel(location.getCity());
                    subcriteriaCity.setValue(location.getCity());
                    subcriteriaCity.setType("location");
                    subcriteriaCity.setSubtype("city");

                    FacetsGeo facetStateToAdd = new FacetsGeo();
                    boolean stateExists = false;
                    for(FacetsGeo facetState: facetCountry.getSubCriteria()) {
                        if(facetState.getType() != null && facetState.getSubtype() != null 
                                && facetState.getType().equalsIgnoreCase("location")
                                && facetState.getSubtype().equalsIgnoreCase("state")
                                && facetState.getValue().equalsIgnoreCase(location.getState())) {
                            facetStateToAdd = facetState;

                            if(facetStateToAdd.getSubCriteria() == null) {
                                facetStateToAdd.setSubCriteria(new ArrayList<FacetsGeo>());
                            }
                            stateExists = true;
                            break;
                        }
                    }

                    if(!stateExists) {
                        facetStateToAdd.setLabel(location.getState());
                        facetStateToAdd.setValue(location.getState());
                        facetStateToAdd.setType("location");
                        facetStateToAdd.setSubtype("state");

                        if(facetStateToAdd.getSubCriteria() == null) {
                            facetStateToAdd.setSubCriteria(new ArrayList<SearchBarFacets>());
                        }

                        facetStateToAdd.getSubCriteria().add(subcriteriaCity);
                        facetCountry.getSubCriteria().add(facetStateToAdd); 
                    } else {
                        facetStateToAdd.getSubCriteria().add(subcriteriaCity);
                        facetCountry.getSubCriteria().add(facetStateToAdd);
                    }
                }
            } 
        }
    }`

1 个答案:

答案 0 :(得分:5)

对于Java 8流解决方案,可以按以下方式完成。

此特定解决方案不会生成与问题中显示的JSON完全相同的JSON,因为我认为状态对象数组(每个对象为状态命名一个键)不是一个好的JSON结构。

如果JSON必须类似于问题中所示,那么此解决方案将为您提供一个良好的开端。

Set<Location> locationSet = Set.of(
        new Location("USA", "AZ", "Phoenix"),
        new Location("USA", "AZ", "Scottsdale"),
        new Location("USA", "AZ", "Peoria"),
        new Location("USA", "MD", "Baltimore"),
        new Location("USA", "MD", "Gaithersburg"),
        new Location("USA", "MD", "OwingsMills"),
        new Location("CA", "ON", "Toronto"));

Map<String, Map<String, List<String>>> countryMap = locationSet.stream()
        .collect(Collectors.groupingBy(Location::getCountry, TreeMap::new,
                Collectors.groupingBy(Location::getState, TreeMap::new,
                        Collectors.mapping(Location::getCity, Collectors.toList()))));

System.out.println(JSONWriter.valueToString(countryMap));

输出

{"CA":{"ON":["Toronto"]},"USA":{"AZ":["Phoenix","Scottsdale","Peoria"],"MD":["OwingsMills","Baltimore","Gaithersburg"]}}