Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List<String> searchList = new ArrayList<String>(7);
        searchList.add("hello");
        searchList.add("world");
        searchList.add("CSS");
        searchList.add("debian");
        searchList.add("linux");
        searchList.add("HTML");
        searchList.add("stack");

        Set<String> targetSet = new HashSet<String>(searchList);
        Set<String> matchSet = findMatches(searchList, targetSet);
        for (String match : matchSet) {
            System.out.println("match:  " + match);
        }
    }

    public static Set<String> findMatches(List<String> searchList, Set<String> targetSet)
            throws InterruptedException, ExecutionException {
        Set<String> locatedMatchSet = new HashSet<String>();

        int threadCount = Runtime.getRuntime().availableProcessors();
        List<List<String>> partitionList = getChunkList(searchList, threadCount);

        if (partitionList.size() == 1) {
            // if we only have one "chunk" then don't bother with a thread-pool
            locatedMatchSet = new ListSearcher(searchList, targetSet).call();
        } else {
            ExecutorService executor = Executors.newFixedThreadPool(threadCount);
            CompletionService<Set<String>> completionService = new ExecutorCompletionService<Set<String>>(executor);
            for (List<String> chunkList : partitionList)
                completionService.submit(new ListSearcher(chunkList, targetSet));

            for (int x = 0; x < partitionList.size(); x++) {
                Set<String> threadMatchSet = completionService.take().get();
                locatedMatchSet.addAll(threadMatchSet);
            }
            executor.shutdown();
        }
        return locatedMatchSet;
    }

    private static <T> List<List<T>> getChunkList(List<T> unpartitionedList, int splitCount) {
        int totalProblemSize = unpartitionedList.size();
        int chunkSize = (int) Math.ceil((double) totalProblemSize / splitCount);

        List<List<T>> chunkList = new ArrayList<List<T>>(splitCount);

        int offset = 0;
        int limit = 0;
        for (int x = 0; x < splitCount; x++) {
            limit = offset + chunkSize;
            if (limit > totalProblemSize)
                limit = totalProblemSize;
            List<T> subList = unpartitionedList.subList(offset, limit);
            chunkList.add(subList);
            offset = limit;
        }
        return chunkList;
    }
}

class ListSearcher implements Callable<Set<String>> {

    private final List<String> searchList;
    private final Set<String> targetSet;
    private final Set<String> matchSet = new HashSet<String>();

    public ListSearcher(List<String> searchList, Set<String> targetSet) {
        this.searchList = searchList;
        this.targetSet = targetSet;
    }

    @Override
    public Set<String> call() {
        for (String searchValue : searchList) {
            if (targetSet.contains(searchValue))
                matchSet.add(searchValue);
        }

        return matchSet;
    }

}