Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast way to compare String[] to List

Tags:

java

algorithm

I would like to compare String arrays to a list with market objects.

I implemented the code like that:

private List<Data> addMarketData(List<Data> list) {
    String[] SEE = new String[]{"Albania", "Bosnia and Herzegovina", "Bulgaria", "Croatia", "Macedonia FYR", "Moldavia", "Montenegro", "Romania", "Serbia", "Slovenia" };
    List<String> seeList = Arrays.asList(SEE);
    String[] CEE = new String[]{"Czech Republic", "Hungary", "Poland", "Slovakia"}; 
    List<String> ceeList = Arrays.asList(CEE);
    for (int i = 0; i < list.size(); i++) {
        for (int j = 0; j < seeList.size(); j++) {
            if(list.get(i).getPropertyCountry().equals(seeList.get(j).toString())) {
                list.get(i).setMarket("SEE");
            }   
        }
        for (int k = 0; k < ceeList.size(); k++) {
            if(list.get(i).getPropertyCountry().equals(ceeList.get(k).toString())) {
                list.get(i).setMarket("CEE");
            }   
        }
    }
    return list;
}

However, I believe that this code produces more overhead than it really should. Especially the for loops. Could I just use one loop?

Therefore, how to make this piece of code much faster?

I appreciate your answer!

like image 573
Carol.Kar Avatar asked Dec 26 '22 05:12

Carol.Kar


2 Answers

Move all the data into a Set<String>:

String[] SEE = ...
Set<String> setSEE = new HashSet<>(Arrays.asList(SEE));
String[] CEE = ...
Set<String> setCEE = new HashSet<>(Arrays.asList(CEE));
for (Data data : list) {
    if (setSEE.contains(data.getPropertyCountry()) {
        data.setMarket("SEE");
    } else if (setCEE.contains(data.getPropertyCountry()) {
        data.setMarket("CEE");
    }
}

This won't generate the overhead you may think. Also, it is faster than your current O(N^2) approach.

Another idea is to move the data of these arrays into a Map<String, String> as proposed by @Narmer, but in this case you should define a value when the country is not found as key in the map.


Since Java 7, you can use diamond operator. For Java 5 and 6, you have to specify the whole generics usage:

Set<String> setSEE = new HashSet<String>(Arrays.asList(SEE));
//...
Set<String> setCEE = new HashSet<String>(Arrays.asList(CEE));
like image 59
Luiggi Mendoza Avatar answered Dec 28 '22 05:12

Luiggi Mendoza


Define seeList and ceeList as HashSets and then use its contains() method. HashSet's contains() has constant time complexity.

Set<String> seeSet = new HashSet<>();
Collections.addAll(seeSet, SEE);

Set<String> ceeSet = new HashSet<>();
Collections.addAll(ceeSet, CEE);

And then:

for (int i = 0; i < list.size(); i++) {
    if (seeSet.contains(list.get(i).getPropertyCountry()) {
        list.get(i).setMarket("SEE");
    }

    if (ceeSet.contains(list.get(i).getPropertyCountry()) {
        list.get(i).setMarket("CEE");
    }
}
like image 43
Natix Avatar answered Dec 28 '22 05:12

Natix