[편평한 데이터 구조화] 구조화된 데이터를 신속하게 만들다

4095 단어
평소에 업무 중에 구조화된 업무, 예를 들어 메뉴, 분류 등을 자주 만나는데 일반적인 저장 방식은 하나의 필드, 예를 들어parentId로 부모 노드를 표시한다.편평한 데이터 구조화 코드 자체는 비교적 간단하지만 최근에 lambda 표현식에 대한 애착이 생겼다. 그리고 [모든 샘플 코드를 없애라]의 정신에 따라 lambda 표현식과java8이 새로 제공한 인터페이스를 이용하여 사용하기에 매우 간결한 도구 유형을 썼다.
talk is cheap,show me the code
public class CollectionUtil {

    /**
     *          
     *
     * @param topParent            
     * @param targets        
     * @param idFunc                
     * @param parentIdFunc           
     * @param setSubFunc           
     */
    public static  List buildTree(R topParent, 
                                           Collection targets,
                                           Function idFunc, 
                                           Function parentIdFunc,
                                           BiConsumer> setSubFunc) {
        if (CollectionUtils.isEmpty(targets)) {
            return Collections.emptyList();
        }

        //            
        Map> map = new HashMap<>();
        targets.forEach(t -> {
            R parentId = parentIdFunc.apply(t);
            map.putIfAbsent(parentId, new ArrayList<>());
            map.get(parentId).add(t);
        });

        List result = map.get(topParent);
        if (result != null) {
            buildTree(result, map, idFunc, setSubFunc);
            return result;
        }
        return Collections.emptyList();
    }

    private static  void buildTree(Collection targets, Map> map,
                                         Function idFunc, BiConsumer> setSubFunc) {
        targets.forEach(t -> {
            List subs = map.get(idFunc.apply(t));
            if (subs != null) {
                setSubFunc.accept(t, subs);
                buildTree(subs, map, idFunc, setSubFunc);
            }
        });
    }

}

 
방법은 5개의 매개 변수에 범형을 더하면 좀 어지러워 보이는데 데모로 바로 갑니다.
@Test
    public void test8() throws JsonProcessingException {
        List categories = new ArrayList<>();
        categories.add(new Category(1, 0));
        categories.add(new Category(2, 1));
        categories.add(new Category(3, 1));
        categories.add(new Category(4, 1));
        categories.add(new Category(5, 2));
        categories.add(new Category(6, 3));
        categories.add(new Category(7, 3));
        categories.add(new Category(8, 3));
        categories.add(new Category(9, 4));
        categories.add(new Category(10, 4));
        categories.add(new Category(11, 0));
        categories.add(new Category(12, 11));
        categories.add(new Category(13, 11));
        categories.add(new Category(14, 12));
        categories.add(new Category(15, 13));

        Collections.shuffle(categories);

        //          
        List tops = CollectionUtil.buildTree(0, categories, Category::getId, Category::getPid, Category::setSubs);

        String result = new ObjectMapper().writeValueAsString(tops);
        System.out.println(result);
    }

    class Category {
        private Integer id;
        private Integer pid;
        private List subs;

        public Category(Integer id, Integer pid) {
            this.id = id;
            this.pid = pid;
        }

        public Integer getId() {
            return id;
        }

        public Integer getPid() {
            return pid;
        }

        public List getSubs() {
            return subs;
        }

        public Category setSubs(List subs) {
            this.subs = subs;
            return this;
        }
    }

이렇게 추출한 후에 코드는 매우 간결하게 변했고 등급 구조가 2층이든 10층이든 모두 문제가 없었다.
성능은 시간적으로 O(N)이다. 자세히 말하면 2N이다. 데이터마다 2차례만 접근할 수 있다. 첫 번째는parentId로 그룹을 나누어 맵을 얻고 두 번째는 맵에서 꺼내 부모 노드에 넣는다.공간적으로 맵을 만들어야 하기 때문에 두 배의 공간을 차지한다.
그나저나 stream API의 Collectors.toMap (Function func) 이 수집기는null의 키를 지원하지 않습니다.

좋은 웹페이지 즐겨찾기