HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Interview coding test: Searcher

Submitted by: @import:stackexchange-codereview··
0
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 -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 Map

Since 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 Comparator

You 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 constructor

new 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 paths

You 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.