Разделение списка, разделенного запятыми, с использованием коллекций и потоков Java

#java #collections

Вопрос:

Я использую строку для инициализации некоторых данных следующим образом:

 private String foods = "burgers:10,apples:20,soda:25"
 

…который передается в этот метод в виде одной строки следующим образом:

 public Map<String, String> getFoods() {
    return getCommaSeperatedFoodsMap(foods);
}
 

…который в вызывает этот метод для разделения данных на соответствующие ключи/значения:

 public Map<String, String> getCommaSeperatedFoodsMap(String foods) {
        if (foods.isEmpty()) {
            return Maps.newHashMap();
        }
        Map<String, String> allFoods = Arrays.stream(foods.split(","))
                .map(s -> s.split(":"))
                .collect(Collectors.toMap(s -> s[0].trim(), s -> s[1].trim()));

        logger.info("Foods are:"   allFoods);

        return allFoods;
    }
 

Затем я могу использовать это для повторения каждой записи карты и передачи разделенной строки в качестве отдельных параметров другому методу:

 public void createFoods() {
        vehicle.getFoods().forEach(this::createFoodData);
 }

public void createFoodData(String foodType, String price) {
//....use data in this method
 

Мой вопрос в том, что я хочу иметь возможность передавать строку и разделять ее на 4 значения на , разделитель следующим образом:

 private String foods = "1:burgers:10:new,2:apples:20:old,3:soda:25:new"
 

…в результате чего мне нужно разделить 4 : разделенных значения и передать их как строковые параметры, как и раньше, для createFoodData(String number, String foodType, String price, String age) которых затем потребуется 4 параметра, например

 iteration 1: '1', 'burgers', '10', 'new'
iteration 2: '2', 'apples', '20', 'old'
etc...
 

Какую коллекцию / интерфейс я должен использовать для достижения этой цели? Я некоторое время был вдали от Java, и мне нужно несколько подсказок.

Комментарии:

1. Я бы предложил использовать пользовательский класс, например Food number , с type файлами , price и age вместо любой структуры данных, такой как вложенная карта.

Ответ №1:

FoodData Должен быть создан класс, содержащий четыре поля (например, с использованием Ломбока @Data и @AllArgsConstructor аннотации).:

 @Data
@AllArgsConstructor
class FoodData {
    private String 
        number, 
        foodType, 
        price, 
        age;

    public FoodData(String ... arr) {
        this(arr[0], arr[1], arr[2], arr[3]);
    }
}
 

Затем метод getFoods() может быть переработан, чтобы немедленно вернуть список FoodData без необходимости повторять карту и вызывать createFoodData :

 public List<FoodData> getFoodData(String foods) {
    return Arrays.stream(foods.split("\s*,\s*")) // Stream<String>
            .map(row -> row.split(":"))            // Stream<String[]>
            .map(FoodData::new)                    // Stream<FoodData>
            .collect(Collectors.toList());
}