Java tutorial
/** * Copyright 1999-2011 Alibaba Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.cobar.client.merger; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import com.alibaba.cobar.client.support.utils.CollectionUtils; /** * This merger implementation is mainly for situations that the original * sub-result lists are all in order.<br> * In this situation, we only need to do the 2nd part of merge-sort algorithm to * sort all of the sub-result lists.<br> * * @author fujohnwang * @since 1.0 * @param <E> */ public class ConcurrentSortMerger<E> implements IMerger<List<E>, List<E>>, InitializingBean, DisposableBean { private boolean usingDefaultExecutor = false; private ExecutorService executor; private Comparator<E> comparator; public List<E> merge(List<List<E>> entities) { List<E> resultList = new ArrayList<E>(); if (CollectionUtils.isNotEmpty(entities)) { if (entities.size() == 1) { resultList.addAll(entities.get(0)); } else { List<List<E>> partialResult = new ArrayList<List<E>>(); int pairs = entities.size() / 2; List<Future<List<E>>> futures = new ArrayList<Future<List<E>>>(); for (int i = 0; i < pairs; i++) { final List<E> llst = entities.get(i * 2); final List<E> rlst = entities.get(i * 2 + 1); futures.add(getExecutor().submit(new Callable<List<E>>() { public List<E> call() throws Exception { return partialSortMerge(llst, rlst); } })); } for (Future<List<E>> f : futures) { try { partialResult.add(f.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } if (entities.size() % 2 == 1) { partialResult.add(entities.get(pairs * 2)); } resultList.addAll(merge(partialResult)); } } return resultList; } protected List<E> partialSortMerge(List<E> llst, List<E> rlst) { List<E> resultList = new ArrayList<E>(); int li = 0, ri = 0; while (li < llst.size() && ri < rlst.size()) { E le = llst.get(li); E re = rlst.get(ri); if (getComparator().compare(le, re) <= 0) { resultList.add(le); li++; } else { resultList.add(re); ri++; } } if (li < llst.size()) { resultList.addAll(llst.subList(li, llst.size())); } if (ri < rlst.size()) { resultList.addAll(rlst.subList(ri, rlst.size())); } return resultList; } public void setExecutor(ExecutorService executor) { this.executor = executor; } public ExecutorService getExecutor() { return executor; } public void afterPropertiesSet() throws Exception { if (getComparator() == null) { throw new IllegalArgumentException( "you must provide a comparator for us to compare the element for merge."); } if (getExecutor() == null) { setExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())); usingDefaultExecutor = true; } } public void destroy() throws Exception { if (usingDefaultExecutor) { getExecutor().shutdown(); } } public void setComparator(Comparator<E> comparator) { this.comparator = comparator; } public Comparator<E> getComparator() { return comparator; } }