patternjavaMinor
Interview coding test: Searcher
Viewed 0 times
interviewcodingtestsearcher
Problem
I did a task for an interview and the solution was not accepted. The task was to implement the class search function by name. The number of classes in the input data from 0 to 100000. Class names are no longer than 32 characters, contains only letters and numbers, are unique.
The application starts with flags
Can you take a look at this and let me know where I went wrong and if is possible to somehow refactor, speed up this implementation (except the normal implementation of cache).
```
import java.text.Collator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Searcher implements ISearcher {
private Map> storage = new HashMap<>();
private Map cache;
public Searcher() {
}
/**
* Refreshes internal data structures for fast search
*
* @param classNames class names in project
* @param modificationDates class modification date in ms
*/
@Override
public void refresh(String[] classNames, long[] modificationDates) {
cache = new HashMap<>();
for (int i = 0; i list = new ArrayList<>();
list.add(new Entity(classNames[i], modificationDates[i]));
storage.put(startChar, list);
} else {
storage.get(startChar).add(new Entity(classNames[i], modificationDates[i]));
}
}
}
/**
* Looking for a suitable class names starting with start
*
* @param start beginning of a class name
* @return an array of length 0 to 12, class names, ordered by modification date
* and lexicographically
*/
@Override
public String[] guess(String start) {
if (!storage.containsKey(start.charAt(0))) return new String[0];
if (cache.containsKey(start)) return cache.get(start);
Collator
The application starts with flags
-Xmx64m -Xms64m -Xss64m. Expected, when the project is opened first time the data is indexed, then searches are performed quickly.Can you take a look at this and let me know where I went wrong and if is possible to somehow refactor, speed up this implementation (except the normal implementation of cache).
```
import java.text.Collator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Searcher implements ISearcher {
private Map> storage = new HashMap<>();
private Map cache;
public Searcher() {
}
/**
* Refreshes internal data structures for fast search
*
* @param classNames class names in project
* @param modificationDates class modification date in ms
*/
@Override
public void refresh(String[] classNames, long[] modificationDates) {
cache = new HashMap<>();
for (int i = 0; i list = new ArrayList<>();
list.add(new Entity(classNames[i], modificationDates[i]));
storage.put(startChar, list);
} else {
storage.get(startChar).add(new Entity(classNames[i], modificationDates[i]));
}
}
}
/**
* Looking for a suitable class names starting with start
*
* @param start beginning of a class name
* @return an array of length 0 to 12, class names, ordered by modification date
* and lexicographically
*/
@Override
public String[] guess(String start) {
if (!storage.containsKey(start.charAt(0))) return new String[0];
if (cache.containsKey(start)) return cache.get(start);
Collator
Solution
Java 8
Since you're already on Java 8, you can use
Java 8
You can also use a number of
According to your implementation, you want to compare
Immutable classes and getters
As hinted above, providing getter methods lets you use method references for your
Deprecated
This constructor is deprecated, and in Java 8, you should consider using the new
You should use
Is there any special reason why you have went with a decidedly non-Unix line-separator (
Also, do consider not hard-coding the file path and take that as an input from
edit: Since you do intend to write to a file using OS-dependent line separator, consider using a
MapSince you're already on Java 8, you can use
Map.computeIfAbsent(K, Function) to put a List into your Map if none exists:storage.computeIfAbsent(startChar, k -> new ArrayList<>())
.add(new Entity(classNames[i], modificationDates[i]));Java 8
ComparatorYou can also use a number of
Comparator methods, starting with Comparator.comparing(Function), to replace the in-line lambda you are using to sort your Stream:// assuming getters are given as such
Comparator COMPARATOR = Comparator.comparing(Entity::getTime).reversed()
.thenComparing(Entity::getName,
Collator.getInstance());According to your implementation, you want to compare
entity2.time - entity1.time first, so you have to reverse the Comparator, then comparing on the name.Immutable classes and getters
As hinted above, providing getter methods lets you use method references for your
Entity class, and you can make it immutable too by final-ing the fields.Deprecated
Date constructornew Date(2015, 11, 11).getTime()This constructor is deprecated, and in Java 8, you should consider using the new
java.time.* APIs:long min = ZonedDateTime.of(LocalDate.of(2015, 11, 11),
LocalTime.MIDNIGHT, ZoneOffset.UTC).toEpochSecond() * 1000;try-with-resources and hard-coding file pathsYou should use
try-with-resources on your FileWriter for safe and efficient handling of the underlying I/O resource.Is there any special reason why you have went with a decidedly non-Unix line-separator (
\r\n) while writing to a seemingly Unix-based filesystem?Also, do consider not hard-coding the file path and take that as an input from
String[] args instead.edit: Since you do intend to write to a file using OS-dependent line separator, consider using a
PrintWriter to do so too...File outputFile = getOutputFile(args); // construct from program inputs
try (PrintWriter printWriter = new PrintWriter(outputFile)) {
// ...
printWriter.println();
// ...
}Code Snippets
storage.computeIfAbsent(startChar, k -> new ArrayList<>())
.add(new Entity(classNames[i], modificationDates[i]));// assuming getters are given as such
Comparator<Entity> COMPARATOR = Comparator.comparing(Entity::getTime).reversed()
.thenComparing(Entity::getName,
Collator.getInstance());new Date(2015, 11, 11).getTime()long min = ZonedDateTime.of(LocalDate.of(2015, 11, 11),
LocalTime.MIDNIGHT, ZoneOffset.UTC).toEpochSecond() * 1000;File outputFile = getOutputFile(args); // construct from program inputs
try (PrintWriter printWriter = new PrintWriter(outputFile)) {
// ...
printWriter.println();
// ...
}Context
StackExchange Code Review Q#127111, answer score: 3
Revisions (0)
No revisions yet.