使用流从列表中获取前3个计数

时间:2016-11-22 09:21:29

标签: java java-8 java-stream

我正在尝试将java7程序转换为java 8.我想使用流API进行下面的输出。

public List<String> getTopThreeWeatherCondition7() {
    List<String> _Top3WeatherList = new ArrayList<String>();
    Map<String, Integer> _WeatherCondMap = getWeatherCondition7();
    List<Integer> _WeatherCondList = new ArrayList<Integer>(_WeatherCondMap.values());
    Collections.sort(_WeatherCondList, Collections.reverseOrder());
    List<Integer> _TopThreeWeathersList = _WeatherCondList.subList(0, 3);
    Set<String> _WeatherCondSet = _WeatherCondMap.keySet();
    Integer count = 0;
    for (String _WeatherCond : _WeatherCondSet) {
        count = _WeatherCondMap.get(_WeatherCond);
        for (Integer _TopThreeWeather : _TopThreeWeathersList) {
            if (_TopThreeWeather == count) {
                _Top3WeatherList.add(_WeatherCond);
            }
        }
    }
    _WeatherCondList = null;
    _WeatherCondMap = null;
    _TopThreeWeathersList = null;
    _WeatherCondSet = null;
    return _Top3WeatherList;

}

1 个答案:

答案 0 :(得分:4)

我强烈建议遵守Java编码约定。使用小写字母而不是_ +大写字母开始变量名称。其次,使用后不要将局部变量分配给null。这已经过时并且会分散代码的实际目的。另外,不要使用未使用的默认值初始化变量(如count = 0)。在这种特定情况下,您还应该在内部循环中声明变量,实际使用它。

另请注意,您要比较Integer引用而不是值。在这种特定情况下,它可能起作用,因为对象来自同一个地图,但你应该避免这种情况。目前尚不清楚是否存在重复值;在这种情况下,这个循环不会做正确的事情。此外,您不应迭代keySet(),只是为每个键执行get查找,因为entrySet()允许一起迭代键和值。

既然你说过,这段代码应该是一个“Java 7程序”,你应该注意“菱形运算符”(<>)的存在,它在创建通用的新实例时不需要重复类型参数类。

您应该首先对条目进行排序,而不是仅对值进行排序并搜索关联的键。

原始代码的干净Java 7变体将是:

static final Comparator<Map.Entry<String, Integer>> BY_VALUE_REVERSED=
    new Comparator<Map.Entry<String, Integer>>() {
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
            return Integer.compare(o2.getValue(), o1.getValue());
        }
    };
public List<String> getTopThreeWeatherCondition7() {
    List<String> top3WeatherList = new ArrayList<>();
    Map<String, Integer> weatherCondMap = getWeatherCondition7();
    List<Map.Entry<String, Integer>> entryList=new ArrayList<>(weatherCondMap.entrySet());
    Collections.sort(entryList, BY_VALUE_REVERSED);
    List<Map.Entry<String, Integer>> topThreeEntries = entryList.subList(0, 3);
    for(Map.Entry<String, Integer> entry: topThreeEntries) {
        top3WeatherList.add(entry.getKey());
    }
    return top3WeatherList;
}

这也正确处理重复。只有在第三名出现平局时,才会选择其中一名有效候选人。

只有你有一个干净的起点,你可以看一下,如何从Java 8功能中受益

  • 您可以从List创建Stream权限并告诉流进行排序
  • ,而不是将内容复制到Map进行排序。
  • 您可以更轻松地创建比较器,甚至可以使用其中一个新的内置比较器
  • 您可以将限制结果的任务链接到三个元素,映射到键并收集结果List直到前面步骤的流:
public List<String> getTopThreeWeatherCondition7() {
    Map<String, Integer> weatherCondMap = getWeatherCondition7();
    List<String> top3WeatherList = 
        weatherCondMap.entrySet().stream()
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .limit(3)
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    return top3WeatherList;
}