Группировка в Java для кортежа, такого как Objects

У меня есть уникальный НАБОР объектов местоположения с такими данными, как

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

Я написал код, который представляет собой набор строк для итерации по набору местоположений и создания объектов страны, содержащих набор объектов состояния, содержащих набор объектов города, с использованием объекта 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);
                    }
                }
            } 
        }
    }`

Как вы сопоставляете Location и FacetsGeo? Что означают такие поля, как метка, значение и т. д. в FacetsGeo? что ты уже испробовал? Перед публикацией вопроса ознакомьтесь с этим: stackoverflow.com/help/минимально-воспроизводимый-пример

Ravindra Ranwala 30.06.2019 05:11

Зачем вам массив состояний? Разве { "USA": { "AZ": ["Phoenix", "Scottsdale","Peoria"], "MD": ["Baltimore", "Gaithersburg","OwingsMills"] } } не был бы лучше JSON?

Andreas 30.06.2019 05:52

Спасибо @Andreas, я попробую ваше решение.

Sri 01.07.2019 00:35

метка: «США», значение: «США», тип: «Местоположение», подтип: «Страна», childFacetsGeo: состояния List<FacetsGeo>.

Sri 01.07.2019 00:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
4
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Это конкретное решение не генерирует точно такой же 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"]}}
Set.of — это Java9++.
NoDataFound 01.07.2019 01:11

@Andreas, не могли бы вы объяснить, что происходит под капотом этого нового API, и есть ли способ получить данные о местоположении в FacetsGeo (любопытно узнать, возможно это или нет)

Sri 01.07.2019 01:22

Другие вопросы по теме