【问题标题】:Search an attribute inside a Vector on Java在 Java 上的 Vector 内搜索属性
【发布时间】:2010-11-06 13:02:29
【问题描述】:

我有一个Vector 的对象,并且必须在里面搜索这些对象的随机属性(例如,一个Plane 类,一个包含PlaneVector;我必须搜索有时发给destination,其他发给pilotName)。

我知道我可以使用Iterator 遍历Vector,但我一直不知道如何更改字符串和对象属性之间的比较。我想过使用switch,但另一种意见会很酷。


更新 1:

我写的代码是这样的(Java n00b alert!):

public int search(String whatSearch, String query){  
    int place = -1;  
    boolean found = false;  
    for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {  
        Plane temp = (Plane) iteraPlane.next();  
        /* Here is where I have to search for one of many attributes (delimited by whatSearch */ 
    }  
return place;  
}

似乎我必须坚持线性搜索(这是我能够付出的代价)。无论如何,我在想如果 Java 有类似 variable variable name 的东西(哎哟!)

【问题讨论】:

  • 你能贴出你试过的代码吗?
  • 我认为这里的关键词是 random 属性。我在下面发布了一个答案,因为我认为您是在询问实现一种算法,该算法在编码算法时搜索您不知道要搜索的内容 for 的内容。如果您不是在问这个问题,那么我建议您完善您的问题以使其更清晰。

标签: java search vector iterator


【解决方案1】:

我假设你的问题是你想要一个方法来搜索基于集合类型的 some property 的结果。 Java 在这方面很弱,因为它最好用具有闭包的语言来表达。你需要的是这样的:

public interface Predicate<T> {
    public boolean evaluate(T t);
}

然后你的搜索方法看起来像:

public static <T> T findFirst(List<T> l, Predicate<T> p) { //use List, not Vector
    for (T t : l) { if (p.evaluate(t)) return t; }
    return null;
}

那么任何人都可以使用这种通用搜索方法。例如,在Integers 的向量中搜索一个数字:

List<Integer> is = ...
findFirst(is, new Predicate<Integer> {
    public boolean evaluate(Integer i) { return i % 2 == 0; }
});

但是你可以用任何你想要的方式来实现谓词;任意搜索

【讨论】:

  • 我同意,谓词似乎非常适合这种情况。
【解决方案2】:

使用Collections.binarySearch 并提供Comparator

编辑:这假设 Vector 已排序。否则,必须进行线性搜索。

【讨论】:

  • 请注意,为此需要使用 Compartor 对 Vector 进行排序
  • 问题是关于搜索 random 属性,因此预先假定集合根据该属性排序的搜索是非常无用的,不是吗?这意味着 is 不是很随机
  • 但每次搜索单个属性时都需要进行排序
【解决方案3】:

equals() 方法是最佳选择。对于这些迭代,您可以执行以下操作:

for (Plane plane: planes) {
   if ("JFK".equals(plane.getDestination())) {
      // do your work in here;
   }
}

或者您可以覆盖Plane 中的equals() 方法,以查看传入的字符串是否与您的目的地(或飞行员)匹配。这将允许您使用Vector 上的indexOf(Object)indexOf(Object, index) 方法返回对象的索引。完成后,您可以使用 Vector.get(index) 为您返回 Object。

Plane.java:

public boolean equals(Object o) {
    return o.equals(getDestination()) ||
           o.equals(getPilot()) ||
           super.equals(o);    

}

这个选项还有很多工作要做,因为您还需要覆盖hashCode() (see documentation)。

【讨论】:

  • 严格来说,如果他不把这个对象放在散列容器中,他就不需要担心hashCode()。但最好从一开始就正确地做。
  • 我同意,最好提前覆盖你的基地。
【解决方案4】:

参见上面的@oxbow_lakes——我认为你想要的不是将String 传递为whatSearch,而是传递一些知道如何获取你感兴趣的属性的sn-p 代码. 对于不太通用的版本:

public static interface PlaneMatcher {
    boolean matches(Plane plane, String query);
}


public int search(PlaneMatcher matcher, String query){  
    int place = -1;  
    boolean found = false;  
    for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {  
        Plane temp = (Plane) iteraPlane.next();  
        if (matcher.matches(temp, query) {
            found = true;
        }
        place++;
    }  
    return place;  
}

...
// example

int pilotNameIndex = search(new PlaneMatcher() {
        boolean matches(Plane plane, String query) {
            // note: assumes query non-null; you probably want to check that earlier
            return query.equals(plane.getPilotName());
        }
    }, "Orville Wright");

(顺便说一句,如果它是您感兴趣的索引而不是 Plane 本身,我不会打扰 Iterator —— 只需使用老式的 for (int i = 0; i &lt; planes.size(); i++) 循环,当你有一个匹配,return i。)

现在,棘手的一点是,您必须搜索的内容是否真的在运行时由任意字符串标识。如果是这种情况,我可以提出两种选择:

  1. 不要将这些值存储为对象字段 -- plane.pilotNameplane.destination -- 完全不。只要有一个Map&lt;String, String&gt;(或者更好的是Map&lt;Field, String&gt;,其中Field 是所有有效字段中的Enum)称为plane.metadata
  2. 将它们存储为对象字段,但如上所述预先填充从字段名称到PlaneMatcher 实例的映射。

例如:

private static final Map<String, PlaneMatcher> MATCHERS = Collections.unmodifiableMap(new HashMap<String, PlaneMatcher>() {{
    put("pilotName", new PlaneMatcher() {
        boolean matches(Plane plane, String query) {
            return query.equals(plane.getPilotName());
        });
    ...
    put("destination", new PlaneMatcher() {
        boolean matches(Plane plane, String query) {
            return query.equals(plane.getDestination());
        });
}}

...

public int search(String whatSearch, String query){  
    PlaneMatcher matcher = MATCHERS.get(whatSearch);
    int place = -1;  
    boolean found = false;  
    for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {  
        Plane temp = (Plane) iteraPlane.next();  
        if (matcher.matches(temp, query) {
            found = true;
        }
        place++;
    }  
    return place;  
}

哦,您可能很想使用反射。别。 :)

【讨论】:

    【解决方案5】:

    一种简单的方法是将比较函数传递给您的搜索例程。或者,如果您需要更快的速度,请使用泛型。

    【讨论】:

    • “如果您需要更快的速度,请使用泛型”?你到底在说什么?
    • 也许程序员可以输入程序的速度?
    猜你喜欢
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多