快速比较String []和List的方法

时间:2014-09-01 09:00:08

标签: java algorithm

我想将String数组与具有市场对象的列表进行比较。

我实现了这样的代码:

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;
}

但是,我相信这段代码会产生比实际应用更多的开销。特别是for循环。我可以只使用一个循环吗?

因此,如何使这段代码更快?

感谢您的回答!

4 个答案:

答案 0 :(得分:7)

将所有数据移至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");
    }
}

这不会产生您可能想到的开销。此外,它比您当前的O(N ^ 2)方法更快。

另一个想法是将这些数组的数据移动到@Narmer建议的Map<String, String>,但在这种情况下,您应该在地图中找不到国家/地区时定义一个值。


从Java 7开始,您可以使用diamond operator。对于Java 5和6,您必须指定整个泛型用法:

Set<String> setSEE = new HashSet<String>(Arrays.asList(SEE));
//...
Set<String> setCEE = new HashSet<String>(Arrays.asList(CEE));

答案 1 :(得分:1)

您可以简单地使用两个HashSet<String>集合来存储国家/地区的名称。HashSet<String>每个项目大约 O(1)时间执行查找,这整个阵列的 O(n)。或者您可以使用一个HashMap<String,String>执行查找,从而生成"SEE""CEE"

示例

Map<String,String> lut = new HashMap<String,String>();
for(String s : new String[]{"Albania", "Bosnia and Herzegovina", "Bulgaria", "Croatia", "Macedonia FYR", "Moldavia", "Montenegro", "Romania", "Serbia", "Slovenia" }) {
    lut.put(s,"SEE");
}
for(String s : new String[]{"Czech Republic", "Hungary", "Poland", "Slovakia"}) {
    lut.put(s,"CEE");
}

for (Data data : list) {
    data.setMarket(lut.get(data.getPropertyCountry()));
}

HashMap<String,String>的生成(以及将数据放入其中)只应执行一次(启动时)。这将提高性能,其因子等于您放入HashMap<String,String>的元素数量(在本例中为14)。

答案 2 :(得分:1)

您可以使用地图而不是列表。

private static final Map<String, String> markets = new HashMap<String,String>(){{
    put("Albania", "SEE");
    put("Bosnia and Herzegovina", "SEE");
    ...
    put("Hungary", "CEE");
    ...
}}

然后咨询

for(Data data: list){
    data.setMarket(markets.get(data.getPropertyCountry()));
}

修改

根据评论,以上是最佳情况。您应该检查data.getPropertyCountry()是否为空(如果允许),并且列表返回的值也为空:

for(Data data: list){
    if(data.getPropertyCountry()!=null){
        String market = markets.get(data.getPropertyCountry());
        data.setMarket(market==null?"default market":market);
    }
    else data.setMarket("default value"); //if needed
}

或者使用美丽的Java 8流接口:

for(Data data: list.stream().filter(p -> p.getPropertyCountry() != null).collect(Collectors.toList())){
    String market = markets.get(data.getPropertyCountry());
    data.setMarket(market==null?"default market":market);
}

答案 3 :(得分:1)

seeListceeList定义为HashSet,然后使用其contains()方法。 HashSet contains() Set<String> seeSet = new HashSet<>(); Collections.addAll(seeSet, SEE); Set<String> ceeSet = new HashSet<>(); Collections.addAll(ceeSet, CEE); 具有恒定的时间复杂度。

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");
    }
}

然后:

{{1}}