返回泛型集合中第一个项目的索引

huangapple go评论62阅读模式
英文:

Return the index of the first item in generics collections

问题

/**
 * 返回满足 aPredicate.test(o) 条件的第一个元素在 someCollection 中的索引,如果没有则返回 -1。
 */
public static <T> int find(Collection<T> someCollection, Predicate<T> aPredicate) {
    List<T> list = new ArrayList<>();
    for (Iterator<T> iterator = someCollection.iterator(); iterator.hasNext(); ) {
        T value = iterator.next();
        if (aPredicate.test(value)) {
            list.add(value);
        }
    }
    return list.indexOf(list.get(0)); // 或者直接返回 list.indexOf(list.get(0))
}

// 对于只适用于整数集合的情况,如何返回第一个元素的索引呢?
英文:
/**
 * Return the index of the first item in someCollection for which * aPredicate.test(o) is true, or -1.
 */
public static &lt;T&gt; int find(Collection&lt;T&gt; someCollection, Predicate&lt;T&gt; aPredicate) {
    List&lt;T&gt; list = new ArrayList&lt;&gt;();
    for (Iterator&lt;T&gt; iterator = someCollection.iterator(); iterator.hasNext(); ) {
        T value = iterator.next();
        if (aPredicate.test(value)) {
            list.add(value);
        }
    }
    return list[0]; // or return list.get(0)
}

With the code above, I cannot use list[0] since it needs to be replaced with list.get(0), but this method is only applicable to the collection of Integers.
How can I return the index of the first element in such case?

答案1

得分: 1

你的函数目的是返回与给定的“Predicate”匹配的“Collection”中第一个元素的索引。因此,你应该存储一个List<int>而不是一个List<T>,如果要返回找到的第一个元素,根本没有存储列表的必要。因此,完全移除缓冲列表,在找到匹配的元素后立即返回。

public static int find(Collection<?> someCollection, Predicate<?> aPredicate) {
    int index = 0;
    for (Iterator<?> iterator = someCollection.iterator(); iterator.hasNext(); ) {
        Object value = iterator.next();
        if (aPredicate.test(value)) {
            return index;
        }
        index++;
    }
    return -1;
}
英文:

The purpose of your function is to return the first index of the first element in a Collection that matches the given Predicate. As such, not only should you be storing a List&lt;int&gt; rather than a List&lt;T&gt;, there's no reason to be storing a list at all if the point is to return the first thing found. As such, remove the buffer list entirely and return as soon as you find a matching element.

public static &lt;T&gt; int find(Collection&lt;T&gt; someCollection, Predicate&lt;T&gt; aPredicate) {
    // Collections don&#39;t necessarily natively support indices, so you must 
    // manually track the current index
    int index = 0;
    for (Iterator&lt;T&gt; iterator = someCollection.iterator(); iterator.hasNext(); ) {
        T value = iterator.next();
        if (aPredicate.test(value)) {
            // A matching element was found, so there&#39;s no point continuing to loop
            return index;
        }
        index++;
    }
    // No element was found, so return the conventional -1
    return -1;
}

答案2

得分: 0

你想要的不是存储 List<T>,而是一个 List<Integer>,基本上,它包含了你找到的元素的索引。你将不得不自己跟踪该索引,以及追踪调用了多少次 iterator.next()

英文:

What you want isn't to store a List&lt;T&gt;, but a List&lt;Integer&gt;, essentially, containing the index of the elements you found. You will have to track that index yourself, but tracking how many calls to iterator.next() you have made.

答案3

得分: 0

让我们首先确保您的方法执行正确的操作:

public static <T> int find(Collection<T> someCollection, Predicate<T> aPredicate) {
    int i = -1;
    for (Iterator<T> iterator = someCollection.iterator(); iterator.hasNext();) {
        ++i;
        T value = iterator.next();
        if (aPredicate.test(value)) {
            return i;
        }
    }
    return -1;
}

让我们看看它是否有效:

public static void main(String[] args) {
    List<Integer> list = List.of(1, 2, 3);
    System.out.println(find(list, x -> x == 4)); // -1
    System.out.println(find(list, x -> x == 2)); // 1
}

虽然它能正常工作,但它是否正确呢?...

public static void main(String[] args) {
    Set<String> set = Set.of("abc", "ade");
    System.out.println(find(set, "abc"::equals));
}

多次运行此代码(使用 Java 9),您会惊讶地发现索引会发生变化。Set 没有任何顺序,而在 Java 9 中添加的不可变集合在创建时会进行一些内部随机化,因此结果可能会完全不正确。想要更广泛的了解,可以查看这里

您可能会认为 Java 有一个通用的接口,用于确定特定集合是否有序,但实际上并没有。因此,除了重新考虑您想要做的事情之外,您真的无法做太多事情,也许会有所帮助。

英文:

Let's first make sure your method does the correct thing:

public static &lt;T&gt; int find(Collection&lt;T&gt; someCollection, Predicate&lt;T&gt; aPredicate) {
	int i = -1;
	for (Iterator&lt;T&gt; iterator = someCollection.iterator(); iterator.hasNext();) {
		++i;
		T value = iterator.next();
		if (aPredicate.test(value)) {
            return i;
        }
    }
    return -1;
}

Let's see if it works:

public static void main(String[] args) {
	List&lt;Integer&gt; list = List.of(1, 2, 3);
	System.out.println(find(list, x -&gt; x == 4)); // -1
	System.out.println(find(list, x -&gt; x == 2)); // 1
}

It does, but is it correct?...

public static void main(String[] args) {
	Set&lt;String&gt; set = Set.of(&quot;abc&quot;, &quot;ade&quot;);
	System.out.println(find(set, &quot;abc&quot;::equals));
}

Run this a few times (with java-9) and be surprised how the index will change. A Set does not have any order and immutable collections added in java-9 do some internal randomization when they are first created, so the results might get entirely incorrect. For a broader read, look here.

You could think that java has a common interface for when a certain Collection would be ordered or not, but it does not. So you can't really do much, other then rethink what you want to do, may be.

huangapple
  • 本文由 发表于 2020年10月22日 00:58:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/64468305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定