简体   繁体   中英

Splitting comma separated list using Java Collections and Streams

I'm using a String to initialise some data as follows:

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

...which is passed into this method as a single string as follows:

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

...which in calls this method to split the data into respective key/values:

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;
    }

I can then use this to iterate each map entry and pass the split string as separate parameters to another method:

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

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

My question is, I want to be able to pass a String and split on 4 values per , delimiter as follows:

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

...whereby I need to split the 4 : separated values and pass them as String parameters as before to createFoodData(String number, String foodType, String price, String age) which will then take 4 params, eg

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

Which Collection / interface should I use achieve this? I've been away from Java for a while a need a few hints.

A class FoodData containing the four fields should be created (eg using Lombok's @Data and @AllArgsConstructor annotation):

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

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

Then the method getFoods() may be refactored to immediately return a list of FoodData without having to iterate a map and call 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());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM