【问题标题】:Most efficient way to order an Array created from a HashSet订购从 HashSet 创建的数组的最有效方法
【发布时间】:2017-07-10 22:42:44
【问题描述】:

我正在研究一种方法,该方法在给定 GPS 坐标的特定半径内创建公交车站的 HashSet,然后将此集合转换为数组。

我想按相对于 GPS 坐标的距离来排序这个数组,这是最有效的方法吗?

public Stop[] possibleStops(GPSCoordinate spot) {
    Set<Stop> viableBusStops = new HashSet<Stop>();
    for(Map.Entry<String, Stop> stopEntry : stops.entrySet()) {
        Stop applicant = stopEntry.getValue();
        Double distance = spot.distance(applicant.getGPSCoordinate());
        if (distance<=threshold) {
            viableBusStops.add(applicant);
        }
    }
    Stop[] stopList = viableBusStops.toArray(new Stop[0])
    return stopList;
}

编辑: 挑战在于“距离”不是 Stop 对象的属性。我想知道我是否可以对那些只计算一次距离的公交车站进行排序。

【问题讨论】:

  • 使用内置的 Collections.sort 方法
  • 创建一个具有stopdistance 属性的StopDistance 类型,并将其而不是Stop 实例存储在临时集合中。相应地排序。

标签: java arrays hashset


【解决方案1】:

构建一个Map&lt;Stop, Double&gt;,将停靠点映射到它们与该点的距离。然后根据距离对条目进行排序。

【讨论】:

    【解决方案2】:

    您可以为此使用 Java 8 Streams:

    public Stop[] possibleStops(GPSCoordinate spot) {
        // dummies
        Map<String, Stop> stops = new HashMap<>();
        double threshold = 10.0;
    
        Stop[] filteredSortedStops = stops.values().stream()
                .collect(Collectors.toMap((stop) -> stop,
                        (stop) -> spot.distance(stop.getGPSCoordinate())))
                .entrySet()
                .stream()
                .filter((entry) -> entry.getValue() <= threshold)
                .sorted(Comparator.comparingDouble(Map.Entry::getValue))
                .map(Map.Entry::getKey)
                .toArray(Stop[]::new);
    
        return filteredSortedStops;
    }
    

    【讨论】:

    • 我喜欢你的做法,但我认为终端操作是错误的。也许你应该在.toArray(Stop[]::new)之前添加一个.map(Map.Entry::getKey)
    【解决方案3】:

    很可能是这种方法:Arrays.sort with Comparator

    注意:您可能应该将计算出的距离缓存到Stop 对象(或包装器)中的所需位置,以便在将对象与Comparator 进行比较时,在排序期间不会多次执行此逻辑

    您也可以考虑使用TreeMap,其中key 是距离,valueStop - 然后提取值并将它们转换为数组。

    【讨论】:

    • 实际上TreeMap 的距离为key 是个坏主意,因为如果多个停靠点与spot 的距离相同,您将遇到问题
    【解决方案4】:

    你考虑过 Treeset with Comparator 吗?

    public class SortByDistance implements Comparator<Distance>{
            public int compare(Distance d1, Distance d2) {
                return d1.getLength().compareTo(d2.getLength());
            }
        }
    
    TreeSet<Distance> names = new TreeSet<Distance>(new SortByDistance());
    

    【讨论】:

      【解决方案5】:

      如果您声明一个函数,该函数将公交车站作为参数并返回其到地点的距离,您可以创建一个比较器,根据函数返回的公交车站到地点的距离对公交车站进行排序。

      但是,为了完成它的工作,比较器可能会多次访问一个给定元素,这意味着对于给定的公交车站,它到该地点的距离最终可能会被计算多次。

      避免这种情况的一种方法是使用一种称为memoization 的技术。本质上,这意味着使用某种缓存来记住函数先前计算的值。

      您可以使用以下辅助方法来实现记忆:

      static <T, R> Function<T, R> memoize(Function<T, R> function) {
          Map<T, R> cache = new HashMap<>();
          return t -> cache.computeIfAbsent(t, function);
      }
      

      现在,为了解决您的问题,您可以创建一个记忆函数,将一个公共汽车站作为参数并返回其到该地点的距离:

      Function<Stop, Double> distanceToSpot = memoize(busStop -> 
          spot.distance(busStop.getGPSCoordinate()));
      

      然后,如下声明Comparator&lt;Stop&gt;

      Comparator<Stop> byDistanceToSpot = Comparator.comparing(distanceToSpot);
      

      最后,使用此比较器对您的公交车站集合进行排序:

      Stop[] viableBusStops = stops.values().stream()
          .filter(busStop -> distanceToSpot.apply(busStop) <= threshold)
          .sorted(byDistanceToSpot) // only sort bus stops within threshold
          .toArray(Stop[]::new);
      

      【讨论】:

        【解决方案6】:

        试试这个。

        public Stop[] possibleStops(GPSCoordinate spot) {
            return stops.values().stream()
                .map(stop -> new AbstractMap.SimpleEntry<>(
                    spot.distance(stop.getGPSCoordinate()), stop))
                .filter(e -> e.getKey() <= threshold)
                .sorted(Comparator.comparing(e -> e.getKey()))
                .map(Entry::getValue)
                .toArray(Stop[]::new);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-19
          • 1970-01-01
          • 1970-01-01
          • 2010-11-16
          • 1970-01-01
          • 1970-01-01
          • 2022-12-18
          相关资源
          最近更新 更多