Группировка по в Java на кортеже типа объектов - PullRequest
2 голосов
/ 30 июня 2019

У меня есть уникальный набор объектов местоположения с данными, такими как

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"]}
        ]

Java POJO для Location.java

Я написал код, который представляет собой набор строк для итерации по множеству местоположенийи создать объекты Country, содержащие набор объектов State, содержащие набор объектов City, используя объект FacetsGeo, и сгенерировать json из этих моделей данных.

Я думаю, что может быть лучший способ сделать это: возможно, с потоковой передачей Java 8API.

Любая помощь оценена, как я уже говорил выше, является примером данных, как построены плоские локации.

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 Ответ

5 голосов
/ 30 июня 2019

Для решения Java 8 Streaming это можно сделать, как показано ниже.

Это конкретное решение не генерирует точно такой же JSON, который показан в вопросе, потому что я не думаю, что массив объектов состоянияс 1 ключом на объект, именующий состояние, является хорошей структурой 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"]}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...