【问题标题】:efficiently find element in array of objects有效地在对象数组中查找元素
【发布时间】:2014-03-09 18:42:01
【问题描述】:

我有这么长的对象数组:

public static class __Location {
    public __Location(int locationId, String locationDesc) {
        this.LocationId = locationId;
        this.LocationDesc = locationDesc;
    }

    public int LocationId;
    public String LocationDesc;
}


public static __Location[] LOCATIONS = { new __Location(100, "Afghanistan"), new __Location(110, "Albania"), new __Location(120, "Algeria"),
        new __Location(130, "American Samoa"), new __Location(140, "Andorra"), new __Location(150, "Angola"), new __Location(160, "Anguilla"),
        new __Location(170, "Antarctica"), new __Location(180, "Antigua And Barbuda"), new __Location(190, "Argentina"), new __Location(200, "Armenia"),
        new __Location(210, "Aruba"), new __Location(220, "Australia"), new __Location(230, "Austria"), new __Location(240, "Azerbaijan"),
        new __Location(250, "Bahamas"), new __Location(260, "Bahrain"), new __Location(270, "Bangladesh"), new __Location(280, "Barbados"),
        new __Location(290, "Belarus"), new __Location(300, "Belgium"), new __Location(310, "Belize"), new __Location(320, "Benin"),
        new __Location(330, "Bermuda"), new __Location(340, "Bhutan"), new __Location(350, "Bolivia"), new __Location(360, "Bosnia And Herzegovina"),
        new __Location(370, "Botswana"), new __Location(380, "Bouvet Island"), new __Location(390, "Brazil"),
        new __Location(400, "British Indian Ocean Territory"), ...

我的问题是如何有效地在这个长数组中搜索一个项目(根据它的键值,即 LocationId)。

【问题讨论】:

  • 如果数组是排序好的,可以使用二分查找。
  • locationId 是唯一的吗?
  • 如果阵列中的所有位置都是唯一的,您应该考虑实现.equals()/.hashCode() 并使用HashSet
  • @Solace 好点,但这需要__Location 来实现Comparable<__Location>,或者使用Comparator<__Location>
  • 请使用Java naming conventions - 类应以PascalCase 命名。 __Location 应该是 Location

标签: java arrays search


【解决方案1】:

使用HashMap可以高效访问项目,时间复杂度为O(1)

Map<Integer, __Location> map = new HashMap<Integer, __Location>();

这个HashMapkeyLocationIdvalue是对应的__Location object

【讨论】:

  • 这需要做一些工作......例如,Integer 密钥来自哪里?
  • @fge Integer 是来自对象的“自动装箱”位置 ID。根本没有真正的工作。
【解决方案2】:

首先:将__Location重命名为Location

第二:你说的是“高效搜索”,很好。现在回答这两个问题:

  • 您要搜索的这个位置来自哪里?是new Location() 的结果吗?这个位置的id?这个位置的字符串?
  • 在您要查找的容器中,现有位置是否已排序?如果是,反对什么?身份证?字符串?

如果没有明确回答这个问题,就不可能回答你的问题。

让我们假设,因为这是最简单的情况,Location 由它的locationId 标识;您知道对于给定的locationIdlocationString 将是唯一的。

为了获得最大效率,您应该在Location 中实现.equals()/.hashCode() 合约并使用HashSet

public static class Location {
    private final int locationId;
    private final String locationDesc;

    public Location(final int locationId, final String locationDesc)
    {
        this.locationId = locationId;
        this.locationDesc = locationDesc;
    }

    @Override
    public int hashCode()
    {
        return locationId;
    }

    @Override
    public boolean equals(final Object obj)
    {
        if (obj == null)
            return false;
        if (this == obj)
            return true;
        if (getClass() != obj.getClass())
            return false;
        final Location other = (Location) obj;
        return locationId == other.locationId;
    }
}

然后使用HashSet&lt;Location&gt; 插入Locations 并使用Set.contains() 方法。

【讨论】:

  • +1 获取缺失信息的全面细分。不过,我想我还是更喜欢Map
  • 但关键是什么?
  • 我会说id - 只是因为这使代码的意图变得清晰。它还允许通过 Set 不支持的 id 进行查找。 OP 使用了 search 这个词,这给我的印象是 OP 想要在给定 id 的情况下找到 Location
  • 嗯,另一个解决方案可能是根据标准使用 Guava 的 Equivalence&lt;Location&gt; ;)
  • @NedNowotny 你的言论没有任何意义;如果您真的想要它的优点,请查看HashMap 的实现。
【解决方案3】:

如果您使用键,为什么不尝试使用地图?

http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

这样,你可以通过它的键来查找一个值,从上下文中我认为这是你想要做的?

【讨论】:

  • Map 是一个合适的接口,但使用哪个实现仍然很重要。例如,我强烈推荐 hashMap 使用不可变键,而不是原始值包装对象以外的任何对象类的 hashSet
【解决方案4】:

考虑使用 HashSet

Set<_location> locationSet = new HashSet<_location>();
locationSet.add(new __Location(130, "American Samoa"));
...
_location searchLocation = //some _location instance;
if (locationSet.contains(searchLocation)) {
  //found it
}

您需要覆盖 _location 类的 hashcode 和 equals 方法,以便相等性由 locationID 确定。

这比需要遍历的数组搜索效率更高。你有 O(1) 的 HashSet 搜索和 O(n) 的数组

【讨论】:

  • 不确定你的意思 你有 O(1) 搜索 HashSet vs O(n) 搜索数组HashSet 有一个 O(1) contains 方法,但这对给定索引的搜索没有帮助。需要详细说明吗?
  • @BoristheSpider 我只是假设 OP 想要搜索和评估给定的 _location 是否包含在集合中。反思一下,如果 OP 实际上对检索值 locationDesc 感兴趣,那么 HashMap 是更好的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 2014-05-01
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-13
相关资源
最近更新 更多