Map<String, Object> 형식을 가지고 있는 fieldsMap 객체를 key값이 customfield 로 시작하고, value는 리스트형식인 것만 필터링을 하고 싶다.
그럴 때 map.entrySet().stream().filter 메서드를 사용하면 맵의 각 엔트리에 대한 스트림을 생성하고, 해당 스트림에 지정된 조건을 만족하는 엔트리들만을 필터링할 수 있다.
조금 더 자세히 알아보자면,
: map.entrySet() 메서드는 맵 내의 각 키-값 쌍을 나타내는 Set<Map.Entry<K,V>> 객체를 반환해준다. 이 메서드는 맵의 모든 엔트리를 포함하는 Set을 반환한다.
entrySet()으로 돌면서 각 키값과 값들을 얻을 수 있기 때문에 유용하다.
: entrySet()이 반환한 Set을 스트림으로 변환해준다. 스트림은 여러 개의 요소를 처리할 수 있는 연속적인 데이터 흐름을 나타내며, 각 요소에 대해 중간 및 최종 연산을 수행할 수 있다.
stream은 데이터를 일련의 연속된 데이터 흐름으로 취급하여 선언적으로 처리할 수 있게 해주는데(즉, 명시적인 반복문 없이도 데이터를 변환, 필터링, 그룹화할 수 있다는 것을 의미함), 이는 반복문과 비교해서 더 간결하고 효율적인 방법을 제공해준다.
: 스트림에서 주어진 조건에 맞는 요소들만을 걸러낸다. filter() 메서드는 Predicate(함수형 인터페이스)를 매개변수로 받으며, 이 predicate는 각 요소에 대해 참 또는 거짓을 반환한다. filter() 메서드는 Predicate가 참을 반환하는 요소들로 이루어진 새로운 스트림을 반환한다.
다시 돌아오자면 나는 Map<String, Object> fieldsMap 이라는 객체를
1. key값이 "customfield" 로 시작할 것,
2. 해당 value값이 List타입인 경우에는 그 리스트가 null이 아니고, 리스트가 비어있지 않고, 모든 요소가 null이 아니고, 리스트의 크기가 0이 아닌 value만 필요하고
3. 해당 value값이 List타입이 아닌 경우에는 customfield로 시작하는 모든 value값
으로 필터링하고싶다.
//fieldsMap 객체
Map<String, Object> fieldsMap =
objectMapper.convertValue(fields, new TypeReference<Map<String, Object>>() {});
//fieldsMap 필터링
List<Map.Entry<String, Object>> customFieldCollect = fieldsMap.entrySet().stream().
filter(stringStringEntry -> stringStringEntry.getKey().startsWith("customfield")).
filter(stringStringEntry -> {
if(stringStringEntry.getValue() instanceof List){
List<?> valueList = (List<?>) stringStringEntry.getValue();
return valueList != null && !valueList.isEmpty() && valueList.stream().noneMatch(Objects::isNull) && valueList.size()!=0;
}
return true;
// Predicate를 매개변수로 받기 때문에 LIST타입이 아닌 경우네는 true로 반환한다.
}).
filter(stringStringEntry -> stringStringEntry.getValue() != null).collect(Collectors.toList());
//필터링한 것들을 새로운 List타입인 List<Map.Entry<String, Object>> customFieldCollect 객체를 만든다.