Java HashMap lookup failing on identical key - java

I have a small bug probably stemming from my misunderstanding of HashMap and it's killing me. I've included a small snippet of test code that illustrates the problem.
I omitted the Prefix class for conciseness, but my prefixes are just arrays of words. They are immutable, so when they are constructed they clone an array of strings passed into the constructor. Hashcode() and equals() methods are implemented so the conditionals pass. Essentially the problem is that I can only dereference the suffix list using prefix1 and not prefix2 (it returns null in the latter case.
FYI, my Hashmap is simply declared as:
// Stores mappings between "prefixes" (consecutive word phrases) and "suffixes" (successor words).
private Map<Prefix, ArrayList<String>> prefixSuffixPairs;
Any help is appreciated.
ArrayList<String> suffixInList = new ArrayList<String>();
suffixInList.add("Suffix1");
suffixInList.add("Suffix2");
String[] prefixWords1 = new String[] {"big", "the"};
Prefix prefix1 = new Prefix(prefixWords1);
String[] prefixWords2 = new String[] {"big", "the"};
Prefix prefix2 = new Prefix(prefixWords2);
prefixSuffixPairs.put(prefix1, suffixInList);
if(prefix1.hashCode() == prefix2.hashCode()) {
System.out.println("HASH CODE MATCH");
}
if(prefix1.equals(prefix2)) {
System.out.println("VALUES MATCH");
}
ArrayList<String> suffixOutList = null;
suffixOutList = prefixSuffixPairs.get(prefix2);
suffixOutList = prefixSuffixPairs.get(prefix1);
public int hashCode() {
int result = 1;
for( int i = 0; i< words.length; i++ )
{
result = result * HASH_PRIME + words[i].hashCode();
}
return result;
}
public boolean equals(Prefix prefix) {
if(prefix.words.length != words.length) {
return false;
}
for(int i = 0; i < words.length; i++) {
if(!prefix.words[i].equals(words[i])) {
return false;
}
}
return true;
}

public boolean equals(Prefix prefix) {
That does not override Object#equals (and thus is not used by the HashMap).
You are merely providing an unrelated method of the same name (overloading) -- but you could call that from the one below:
Try
#Override
public boolean equals(Object prefix) {
The #Override is not strictly necessary, but it would have enabled the compiler to detect this problem if you had applied it to your first method (you get an error when your assertion to override is mistaken).

Related

Search an ArrayList for values in another ArrayList

I have two different ArrayList instances, one of type Container and one of type String. The first is a list of "banned goods" (strings) for a country, and the other is a list of containers on a ship. The ship travels through the country, and the containers are searched for the banned goods. If the container contains the banned goods, that container should be removed/deleted.
public Customs(String country)
{
countryName = country;
bannedGoods = new ArrayList<String>();
}
public Ship(String n, double weight)
{
emptyWeight = totalWeight = weight;
name = n;
containers = new ArrayList<Container>();
}
I already have a method in the Ship class that removes the container:
public void removeContainer(int i)
{
if(i >= 0 && i < containers.size()) {
Container r = containers.remove(i);
totalWeight = totalWeight - r.getWeight();
}
}
I am trying to create an method to inspect the ship for the containers. I want to use two for-loops for each of the arrays, but I can't seem to get it right! Can someone help me use the two loops to search the arrays? Additionally, I think that I will need to use an iterator (the remove function, specifically) in the loop, but that is also confusing for me. Should the iterator remove method replace the method I already wrote in class ship? Here is what I have:
public void inspect(Ship ship)
{
for (String good : bannedGoods) {
for (String con : containers) {
if (con.contains(good) {
container.remove();
}
}
}
And here is my attempt at the iterator:
for(String good : bannedGoods) {
Iterator<String> it = ship.containers.iterator();
while (it.hasNext())
if (ship.contains(good))
it.remove();
}
I don't think you need 2 for loops. You should iterate over banned goods & simply remove it from the containers.
Also, Assuming that containers list is of type string as this is mentioned in your fist line : I have two different arrayLists of the same type String
public void inspect(Ship ship, ArrayList<String> bannedGoods){
if (ship == null || bannedGoods == null || bannedGoods.isEmpty())
return;
for(String good : bannedGoods){
ship.containers.remove(good);
}
}
If, Containers is of type Container and it contains a list of containers(Arraylist of string) which is accessible via the method get_containers(), the following would work:
public void inspect(Ship ship, ArrayList<String> bannedGoods){
if (ship == null || bannedGoods == null || bannedGoods.isEmpty())
return;
for(String good : bannedGoods){
for(Container container : ship.containers){
container.get_containers().remove(good);
}
}
}
You can stick to the methods you are using at the moment. But keep in mind that you either need to use the iterator's remove method or not use iterators. So to use your remove method, either implement Iterable or simply use indexes instead of iterators:
for (int i = 0; i < bannedGoods.size(); i++)
{
for (int j = 0; j < containers.size();) // NOTE: no j++ here
{
Container c = containers.get(j);
if (c.contains(bannedGoods.get(i))
c.removeContainer(j);
else
j++; // only if you don't remove the container increment
// j - when removing the next element gets current
// index
}
}
You're actually pretty close, and you've done a good job of focusing on object-oriented programming principles while designing your classes. I think the things you need to focus on now are just being more careful with your types. Below are some suggested modifications to your classes (Container isn't shown, but I'm assuming it has a public boolean contains (String s) method that checks whether the container has a certain good s inside.
import java.util.*;
public class Ship implements Iterable<Container> {
private double emptyWeight, totalWeight, weight;
private String name;
private List<Container> containers = new ArrayList<Container>();
public Ship(String n, double weight) {
emptyWeight = totalWeight = weight;
name = n;
}
private void removeContainer(int i) {
if (i >= 0 && i < containers.size()) {
Container r = containers.remove(i);
totalWeight = totalWeight - r.getWeight();
}
}
public Iterator<Container> iterator() {
return new Iterator<Container> {
private index = 0;
private Container previous = null;
public boolean hasNext() {
return index < containers.size();
}
public Container next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
previous = containers.get(index++);
return previous;
}
public void remove() {
if (previous == null) {
throw new IllegalStateException();
}
removeContainer(containers.indexOf(previous));
previous = null;
}
};
}
}
I suggest keeping removeContainer within your Ship class since it's responsible for keeping track of how its weight changes when a container is removed. For the same reason, don't allow external classes to directly access its containers list. That way you can prevent other code from adding or removing values from that list without updating the weight correctly. I'd suggest making the containers list private, and expose an Iterator to allow users of the class to interact with the containers.
Within your Customs class, you'd use the Iterator's remove method to remove offending Container instances:
import java.util.*;
public class Customs {
private String countryName;
private List<String> bannedGoods = new ArrayList<String>();
public Customs(String country) {
countryName = country;
}
public void inspect(Ship ship) {
for (String good : bannedGoods) {
for (Iterator<Container> it = ship.iterator(); it.hasNext();) {
Container container = it.next();
if (container.contains(good) {
it.remove();
}
}
}
}
}

Comparing Array Values and HashMap

I was making a rock paper scissors game and I'm supposed to save the last four throws of the user into a HashMap. The last four throws will be inside a Pattern class. I have it so that if the pattern is already in the HashMap, then the value will be incremented by one, showing that the user have repeated that pattern one time. The patterns will be used to predict the user next move. However, when I compare the two patterns, the one in the HashMap and the one I just passed in, even though they are not the same, it returns that they are the same. I have tried looking into this for a while but I couldn't find out what's wrong. Some help would be greatly appreciated! The error comes right at the second input. If I input R, it will save it in the HashMapbut when I input anything else, it will throw a NullPointerException, which I think because the new pattern is not stored inside the hashmap but I tried to get the value of it since the program thinks that it is equal to the one already inside the HashMap. I think the problem is inside the equals() in Pattern but I'm not entirely sure.
import java.util.*;
public class RockPaperScisors{
public static void main(String[] args){
Scanner key = new Scanner(System.in);
Pattern pattern = new Pattern();
Pattern pattern1;
Computer comp = new Computer();
boolean stop = false;
int full=0;;
while ( !stop ){
System.out.println("Enter R P S. Enter Q to quit.");
char a = key.next().charAt(0);
if ( a == 'Q' ){
stop = true;
break;
}
pattern.newPattern(a);
char[] patt = pattern.getPattern();
for ( int i = 0; i < patt.length; i++ ){
System.out.print(patt[i] + " ");
}
pattern1 = new Pattern(patt);
comp.storePattern(pattern1);
System.out.println();
System.out.println("Patterns: " + comp.getSize());
full++;
}
}
}
import java.util.*;
public class Pattern{
private char[] pattern;
private int full = 0;
public Pattern(){
pattern = new char[4];
}
public Pattern(char[] patt){
pattern = patt;
}
public char[] getPattern(){
return pattern;
}
public void newPattern(char p){
if ( full <= 3 ){
pattern[full] = p;
full ++;
}
else{
for (int i = 0; i <= pattern.length-2; i++) {
pattern[i] = pattern[i+1];
}
pattern[pattern.length-1] = p;
}
}
public int HashCode(){
char[] a = pattern;
return a.hashCode();
}
public boolean equals( Object o ) {
if( o == this ) { return true; }
if(!(o instanceof Pattern)){ return false; }
Pattern s = (Pattern) o;
if (Arrays.equals(s.getPattern(), pattern))
System.out.println("Yes");
return Arrays.equals(s.getPattern(), pattern);
}
}
import java.util.*;
import java.util.Map.Entry;
public class Computer{
private HashMap<Pattern, Integer> map;
public Computer(){
map = new HashMap <Pattern, Integer>();
}
public void storePattern(Pattern p){
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
}
else
map.put(p, 0);
}
public int getSize(){
return map.size();
}
}
Your HashCode is wrong.
It should be written in lower case.
public int hashCode()
In order to make sure that the method is overwritten, use the #Override annotation.
As noted by another answer, the first thing to do is rename and annotate your hashcode() method.
And then, you also have to fix it. It uses
char[] a = pattern;
return a.hashCode();
This means it uses the char[] object's hashCode() function. But that function is inherited directly from Object, and gives you a different hash code for two equal character arrays. For example, try this:
char[] c = { 'a','b','c' };
char[] d = { 'a','b','c' };
System.out.printf("%d %d%n", c.hashCode(), d.hashCode());
And you'll see that it prints two different numbers.
So you need to use a better hash code function. You can make your own, or use Arrays.hashCode(pattern) (there is no need for the local a variable). The important thing is that when two Patterns are equal according to the equals() method, they should have the same hash code.
What happens in your case is that you look up the HashCode by testing equality of all the entry keys (I'll get to that in a minute, it's a bad thing to do), so equals tell you you have the same key in the hash map. But the hash map itself uses the hashCode() method in get() to locate the object. And according to the hashCode() method, there is no object in the hash map that has the same key!
So they must always agree when the objects are equal.
Now, as for your method of looking up the object:
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
} else
map.put(p, 0);
This is not how you use a Map. The whole point of a HashMap is that you can see if it contains a certain key or not in O(1). What you are doing is iterating it and comparing - and that`s O(N), very wasteful.
If you implement your hashCode() properly, you can just look it up by doing map.containsKey(p) instead of that loop. And if you are certain that you are not putting null values in the map, you can simply use get() to get your pattern:
Integer time = map.get(p);
if ( time == null ) {
map.put( p, 0 );
} else {
map.put( p, time+1);
}
(You don't need to use ++, because you are not actually using time after you put it in the map).
It's entirely possible that the issue in Pattern#HashCode.
The first issue is that it's not being used (it should be Pattern#hashCode), the second is that it's not calculating what you think it is.
You may find java.util.Arrays#hashCode very useful, changing the backing from an array to a List would also work.
As a side note, Pattern is not a great choice for the name of that class, as it clashes with java.util.regex.Pattern. This is more of a problem in this case than it might be otherwise, as it can be used with Scanner.

How to compare value of array of objects?

There is a collection of 20 objects of a POJO class. I Want to write a method that return objects with distinct value. Now this is my Pogo class
class Student {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName( String firstName ) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName( String lastName ) {
this.lastName = lastName;
}
}
Now i want some method which returns unique last names values. I could not understand which logic i have to put in this.
If you are using something like Eclipse, you can right-click the source and select Source > "Generate hashCode() and equals()...". Doing so will yield something like this:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
Then, you'll want to add your objects to an instance of Set, maybe HashSet. Sounds like you can just return the populated Set then.
See also this.
EDIT: Note that I am not suggesting to put all of this on the Student class. The code shown above goes on Student, but the method that returns the set of distinct students goes somewhere else.
EDIT 2: If you are only interested in unique last names, you could modify hashCode() and equals() to not consider first name, but I concede that this would be quite unintuitive and recommend to avoid this in any circumstance other than an academic exercise. So, more correct might be to layer on an instance of Comparator that only considers last name--see doc and this.
You can use an Arraylist, it has a built in function called .contains() which checks if the arrayList contains a specific value. So you would create an arrayList of last names and if it doesn't exist in the array list, just add it. See http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ArrayList.html#contains(java.lang.Object)
You can try to use Set, if you need to get only one field, or Map, if you need to know object(student) with this field.
If you need to know all distinct Students (pair: first name + surname), you need to override getHashCode() and equals methods and use HashSet, HashMap
An easy way (for a beginner) to do this is just create a new array (same size of the input array). Then to loop through your array then compare every value to every other value in the array. If you can't find a match, then put this value in the new array.
Pseudo code:
public static Student[] GetUniqueLastNames(Student[] students){
Student[] retArray;//new array
for(i = 0; i < students.size; i++){
unique = true
for(j=0; j < students.size; j++){
if(i != j){//make sure its not comparing the same value
if(students[i].lastname.equals(students[j].lastname)){
unique = false
break
}
}
}
if(unique){
retArray[i] = students[i]
}
}
return retArray
}
Note: There are far better ways of doing this, but this is a nice basic way to do it if you're learning Java (or programming in general).
If you don't care about keeping the order of the objects, you can use a set:
public static <S extends Student> Collection<S> uniqByLastName(Collection<S> source){
TreeSet<S> result = new TreeSet<S>(new Comparator<S>() {
#Override
public int compare(S s1, S s2) {
return s1.getLastName().compareTo(s2.getLastName());
}
});
result.addAll(source);
return result;
}
If you care about the order
public static <S extends Student> Collection<S> uniqByLastName(Collection<S> source){
Collection<S> result = new ArrayList<S>();
Set<String> addedStudents = new HashSet<String>();
for(S student : source){
String lastName = student.getLastName();
if(!addedStudents.contains(lastName)){
result.add(student);
addedStudents.add(lastName);
}
}
return result;
}
If you want to modify the collection without returning a new one
public static <S extends Student> void uniqByLastName(Collection<S> source){
Set<String> addedStudents = new HashSet<String>();
Iterator<S> iterator = source.iterator();
while(iterator.hasNext()){
S student = iterator.next();
String lastName = student.getLastName();
if(addedStudents.contains(lastName)){
iterator.remove();
} else {
addedStudents.add(lastName);
}
}
}
If you are using Java 8, you can use lambda expression to solve it. Using following code snippet should solve your problem:
list.stream().collect(Collectors.toMap(Student::getLastName, p -> p, (p, q) -> p)).values();
Note: it will return first student with a given last name and as you might have already guessed, you don't need to override equals and hashcode.

Java class that efficiently handle the contains operation

I'm using inside an iterative algorithm an HashSet that is dynamically enlarged at each algorithm iteration by adding new objects (via method add). Very frequently I check if a generated object has been already put inside the HashSet by using the contains method. Observe that the HashSet may include several thousand objects.
Here follows a citation from the doc about class HashSet:
"This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets."
Apart from other considerations provided inside the doc (not reported for simplicity), I see that add and contains are executed in constant time.
Please, can you suggest another data structure in Java that provides better performance for the "contains" operation with respect to my problem?
Classes from Apache Commons or Guava are also accepted.
The performance of HashSet.contains() will be as good as you can get provided your objects have a properly implemented hashCode() method. That will ensure proper distribution among the buckets.
See Best implementation for hashCode method
As other answers already stated "constant time" is the best runtime-behaviout you can get.
If you will get it does depend on your hashcode-implementation, but since you use the NetBeans suggestion you shouldn't be too bad there.
As to how to keep the "constant time" as small as possible:
try to allocate your HashSet large enough from the very beginning to avoid costly rehash-operations
You can cache your calculated hashcode the first time hashCode() is called and return the cached value later on. There should be no need to add some triggering-mechanism to clear the cache on object-updates, since your relevant fields should be immutable - if they aren't you are bound to run into trouble using HashSet anyway.
You can let your object remember if it has been put in that hashset. Just have a boolean field to store if it was added to the hash set. Then you don't need to call contains on the HashSet but just read the field value of your object. This method will only work if the object is put in exactly one hashset that will check the boolean field.
It might be extended to a constant number of hashsets using java.util.BitSet in the object contained in the hashset where every hashset can be identified by a unique integer when the number of hashsets is known before the algorithm starts.
Since you are saying that you are calling contains frequently, it makes sense to replace newly generated objects with equal existing objects (object pooling), since the overhead of that will amortize by having contains being only a single field read.
As requested here is some sample code. The special set implementation is about 4 times faster than a normal hash set on my machine. However the question is how well this code reflects your use case.
public class FastSetContains {
public static class SetContainedAwareObject {
private final int state;
private boolean contained;
public SetContainedAwareObject(int state) {
this.state = state;
}
public void markAsContained() {
contained = true;
}
public boolean isContained() {
return contained;
}
public void markAsRemoved() {
contained = false;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + state;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SetContainedAwareObject other = (SetContainedAwareObject) obj;
if (state != other.state)
return false;
return true;
}
}
public static class FastContainsSet extends
HashSet<SetContainedAwareObject> {
#Override
public boolean contains(Object o) {
SetContainedAwareObject obj = (SetContainedAwareObject) o;
if (obj.isContained()) {
return true;
}
return super.contains(o);
}
#Override
public boolean add(SetContainedAwareObject e) {
boolean add = super.add(e);
e.markAsContained();
return add;
}
#Override
public boolean addAll(Collection<? extends SetContainedAwareObject> c) {
boolean addAll = super.addAll(c);
for (SetContainedAwareObject o : c) {
o.markAsContained();
}
return addAll;
}
#Override
public boolean remove(Object o) {
boolean remove = super.remove(o);
((SetContainedAwareObject) o).markAsRemoved();
return remove;
}
#Override
public boolean removeAll(Collection<?> c) {
boolean removeAll = super.removeAll(c);
for (Object o : c) {
((SetContainedAwareObject) o).markAsRemoved();
}
return removeAll;
}
}
private static final Random random = new Random(1234L);
private static final int additionalObjectsPerIteration = 10;
private static final int iterations = 100000;
private static final int differentObjectCount = 100;
private static final int containsCountPerIteration = 50;
private static long nanosSpentForContains;
public static void main(String[] args) {
Map<SetContainedAwareObject, SetContainedAwareObject> objectPool = new HashMap<>();
// switch comment use different Set implementaiton
//Set<SetContainedAwareObject> set = new FastContainsSet();
Set<SetContainedAwareObject> set = new HashSet<>();
//warm up
for (int i = 0; i < 100; i++) {
addAdditionalObjects(objectPool, set);
callSetContainsForSomeObjects(set);
}
objectPool.clear();
set.clear();
nanosSpentForContains = 0L;
for (int i = 0; i < iterations; i++) {
addAdditionalObjects(objectPool, set);
callSetContainsForSomeObjects(set);
}
System.out.println("nanos spent for contains: " + nanosSpentForContains);
}
private static void callSetContainsForSomeObjects(
Set<SetContainedAwareObject> set) {
int containsCount = set.size() > containsCountPerIteration ? set.size()
: containsCountPerIteration;
int[] indexes = new int[containsCount];
for (int i = 0; i < containsCount; i++) {
indexes[i] = random.nextInt(set.size());
}
Object[] elements = set.toArray();
long start = System.nanoTime();
for (int index : indexes) {
set.contains(elements[index]);
}
long end = System.nanoTime();
nanosSpentForContains += (end - start);
}
private static void addAdditionalObjects(
Map<SetContainedAwareObject, SetContainedAwareObject> objectPool,
Set<SetContainedAwareObject> set) {
for (int i = 0; i < additionalObjectsPerIteration; i++) {
SetContainedAwareObject object = new SetContainedAwareObject(
random.nextInt(differentObjectCount));
SetContainedAwareObject pooled = objectPool.get(object);
if (pooled == null) {
objectPool.put(object, object);
pooled = object;
}
set.add(pooled);
}
}
}
Anothe Edit:
using the following as the Set.contains implementation makes it about 8 times faster than a normal hashset:
#Override
public boolean contains(Object o) {
SetContainedAwareObject obj = (SetContainedAwareObject) o;
return obj.isContained();
}
EDIT:
This technique has a bit with the class enhancement of OpenJPA in common. The enhancement of OpenJPA enables a class to track its persistent state which is used by the entity manager. The suggested method enables an object to track if itself is contained in a set which is used by the algorithm.

Print Tree components

I am new to java and I want to create a very simple "word completion " program. I will be reading in a dictionary file and recursively adding the words into a Node array (size 26). I believe I have managed to do this successfully but I am not sure how to go through and print the matches. For the sake of testing, I am simply inserting 2 words at the moment by calling the function. Once everything is working, I will add the method to read the file in and remove junk from the word.
For example: If the words "test" and "tester" are inside the tree and the user enters "tes", it should display "test" and "tester".
If somebody could please tell me how to go through and print the matches (if any), I would really appreciate it. Full code is below.
Thank you
What you implemented is called "trie". You might want to look at the existing implementations.
What you used to store child nodes is called a hash table and you might want to use a standard implementations and avoid implementing it yourself unless you have very-very specific reasons to do that. Your implementation has some limitations (character range, for example).
I think, your code has a bug in method has:
...
else if (letter[val].flag==true || word.length()==1) {
return true;
}
If that method is intended to return true if there are strings starting with word then it shouldn't check flag. If it must return true if there is an exact match only, it shouldn't check word.length().
And, finally, addressing your question: not the optimal, but the simplest solution would be to make a method, which takes a string and returns a node matching that string and a method that composes all the words from a node. Something like this (not tested):
class Tree {
...
public List<String> matches(CharSequence prefix) {
List<String> result = new ArrayList<>();
if(r != null) {
Node n = r._match(prefix, 0);
if(n != null) {
StringBuilder p = new StringBuilder();
p.append(prefix);
n._addWords(p, result);
}
}
return result;
}
}
class Node {
...
protected Node _match(CharSequence prefix, int index) {
assert index <= prefix.length();
if(index == prefix.length()) {
return this;
}
int val = prefix.charAt(index) - 'a';
assert val >= 0 && val < letter.length;
if (letter[val] != null) {
return letter[val].match(prefix, index+1);
}
return null;
}
protected void _addWords(StringBuilder prefix, List<String> result) {
if(this.flag) {
result.add(prefix.toString());
}
for(int i = 0; i<letter.length; i++) {
if(letter[i] != null) {
prefix.append((char)(i + 'a'));
letter[i]._addWords(prefix, result);
prefix.delete(prefix.length() - 1, prefix.length());
}
}
}
}
Maybe a longshot here, but why don't you try regexes here? As far as i understand you want to match words to a list of words:
List<String> getMatches(List<String> list, String regex) {
Pattern p = Pattern.compile(regex);
ArrayList<String> matches = new ArrayList<String>();
for (String s:list) {
if (p.matcher(s).matches()) {
matches.add(s);
}
}
return matches
}

Categories

Resources