Here is a test task from a company, where I'd like to work eventually. I solved all they wanted to me to do, however failed to get an interview. I do not know what is wrong with my solution, because it IS working fine and fast.
I do not have any real experience in programming, and will be very grateful if some java-veteran show me some flaws in my solution and also give any advice how to improve my skill in programming.
Here's the task itself.
"Imagine that you - the developer from the ancient times, when IDE were only start to exist. You have big project in Java with hundreds of thousands files. To get your life more easy, you decided to implement the class search function by its name. For convenience, you enter only the first letters of the name of the class, IDE gives you a list of 12 classes that start with the characters entered. In the list classes are sorted by last modification (recently saved at the beginning), if changed at the same time - sorted lexicographically.
It is expected that when the project is opened, data is indexed one time, then searches are performed quickly. That class search function will be used not only by yourself."
Decision must have a class with a default constructor that implements the interface
ISearcher
.
That is the searcher-class
class Searcher implements ISearcher { private SortedMap<String, Long> classes = new TreeMap<>(); @Override public synchronized void refresh(String[] classNames, long[] modificationDates) { Timer.start("One-time indexing"); /* Indexing data - adding arrays sorted by map keys. */ for (int i = 0; i< classNames.length; i++){ classes.put(classNames[i], modificationDates[i]); } Timer.finish(); } @Override public synchronized String[] guess(String start) { Timer.start("Search"); ArrayList<String> list = new ArrayList<>(); //auxiliary list for transferring data from map to array String[] result; //resulting list of class names //If search string is not empty: if(start.length() > 0) { //Searching string in map char nextLetter = (char) (start.charAt(start.length() - 1) + 1); String end = start.substring(0, start.length()-1) + nextLetter; //Result map SortedMap<String, Long> map = classes.subMap(start, end); //Sort all results by last mod.date Map <String, Long> sortedSet = sortByValue(map); list.addAll(sortedSet.keySet()); //Printing results (no more than 12) if (map.size() < 12) { result = new String[map.size()]; for (int i = 0; i < map.size(); i++) { result[i] = list.get(i); } } else { result = new String[12]; for (int i = 0; i < 12; i++) { result[i] = list.get(i); } } Timer.finish(); return result; } //If search string is empty - 12 last modified classes printed. list.addAll(sortByValue(classes).keySet()); result = new String[12]; for (int i = 0; i<12; i++){ result[i] = list.get(i); } Timer.finish(); return result; } /* Auxiliary method, creating linked hash map to sort by value instead of key. */ private static Map<String, Long> sortByValue(Map<String, Long> map) { LinkedHashMap<String, Long> result = new LinkedHashMap<>(); //Create a set of records <String, Long>, to implement custom comparator. SortedSet<Map.Entry<String, Long>> sortedEntries = new TreeSet<>( new Comparator<Map.Entry<String, Long>>() { @Override public int compare(Map.Entry<String, Long> e1, Map.Entry<String, Long> e2) { //Sort by value int res = e1.getValue().compareTo(e2.getValue()); //If values are equal - sort by key return res != 0 ? res : e1.getKey().compareTo(e2.getKey()); } } ); sortedEntries.addAll(map.entrySet()); for (Map.Entry<String, Long> e : sortedEntries){ result.put(e.getKey(), e.getValue()); } return result; } }
This is ISearcher interface
public interface ISearcher { /** * Refreshes internal data structures to find it easily * @param classNames project classes' names * @param modificationDates modification date in ms format since 1 jan 1970 */ void refresh(String[] classNames, long[] modificationDates); /** * Seeking a suitable class names * The name must begin with the 'start' * @param start the beginning of a class name * @return an array of length 0 to 12, class names, sorted by date modifications and lexicographic. */ String[] guess(String start); }
Here is all my (working) solution on Github.