skip to Main Content

values in the code below comes from redis. What’s the best way to convert it back to a list of Items. I am new to Java and have this code below but I am hoping there’s a better way?

@AllArgsConstructor
public class Item {
  public String key;
  public Map<String, Integer> values;
}


public static List<Item> getItems() {

  Map<String, String> values = Map.of("k1", "{"key1":1,"key2":2}", "k2", "{"key1":3,"key2":4}");
  
  List<Item> items = values.entrySet().stream().map(entry -> {
    try {
      TypeReference<HashMap<String, Integer>> typeRef = new TypeReference<HashMap<String, Integer>>() {};
      var itemValues = new ObjectMapper().readValue(entry.getValue(), typeRef);
      return Optional.of(new Item(entry.getKey(), itemValues));
    } catch (JsonProcessingException ex) {
      Optional<Item> emptyItem = Optional.empty();
      return emptyItem;
    }
  }).flatMap(Optional::stream).collect(Collectors.toList());
  return items;
}

2

Answers


  1. Immutable values should be declared as constants. The part that throws an exception in the lambda expression should be a separate method.

    static final TypeReference<HashMap<String, Integer>> TYPEREF_MAP =
        new TypeReference<HashMap<String, Integer>>() {};
    
    static final Map<String, String> ITEM_VALUES = Map.of(
        "k1", "{"key1":1,"key2":2}",
        "k2", "{"key1":3,"key2":4}");
    
    static final HashMap<String, Integer> FAILED_MAP = new HashMap<>();
    
    static HashMap<String, Integer> toMap(String s) {
        try {
            return new ObjectMapper().readValue(s, TYPEREF_MAP);
        } catch (JsonProcessingException e) {
            return FAILED_MAP;
        }
    }
    
    public static List<Item> getItems() {
        return ITEM_VALUES.entrySet().stream()
            .map(entry -> new Item(entry.getKey(), toMap(entry.getValue())))
            .filter(item -> item.getValues() != FAILED_MAP)
            .collect(Collectors.toList());
    }
    
    Login or Signup to reply.
  2. Instead of using Optional to manage the default case, you can use Stream’s flatMap.

    MAPPER.readerForMapOf is a shortcut of new TypeReference<..>

    public class Example {
        
        static final ObjectMapper MAPPER = new ObjectMapper();
        
        static final Map<String, String> ITEM_VALUES = Map.of(
            "k1", "{"key1":1,"key2":2}",
            "k2", "{"key1":3,"key2":4}"
        );
    
        static Stream<Item> toItemOrEmpty(Map.Entry<String, String> entry) {
            try {
                return Stream.of(
                    new Item(
                        entry.getKey(),
                        MAPPER.readerForMapOf(Integer.class).readValue(entry.getValue())
                    )
                );
            } catch (Exception e) {
                return Stream.empty();
            }
        }
    
        public static List<Item> getItems() {
            return ITEM_VALUES
                .entrySet()
                .stream()
                .flatMap(Example::toItemOrEmpty)
                .collect(Collectors.toList());
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search