Java的数组indexOf在哪里?


198

我必定会遗漏一些非常明显的东西,但是我已经四处搜寻,找不到这种方法。

Answers:


234

使用Arrays实用程序类可以通过两种方法来完成此任务。

如果该数组未排序并且不是原始数组:

java.util.Arrays.asList(theArray).indexOf(o)

如果数组原始数组且未排序,则应使用其他答案之一(例如KeremBaydoğanAndrew McKinlayMishax)提供的解决方案。上面的代码即使theArray是原始可能(可能会发出警告),但是您仍然会得到完全错误的结果。

如果数组已排序,则可以使用二进制搜索来提高性能:

java.util.Arrays.binarySearch(theArray, o)

3
我很确定,至少对于Java 1.6,这个答案是错误的:download.oracle.com/javase/6/docs/api/java/util / ... asList将参数列表转换为列表,而不是参数本身。
Alexandru

11
@Alexandru Ellipsis处理是语法糖。如果您输入的T...是实T[]参,则实参的实际运行时类型为,并且传递零个或多个类型的参数会T导致将它们包装到新构造的数组中并传递。如果传递的参数已经是类型T[],则绕过语法糖。
Jeffrey Hantin

7
我明白你的意思。不过,解决方案(.indexOf)对基本元素无效。
Alexandru

53
由于没有人提及:Arrays.asList使用已经存在的数组作为支持。(即,不必担心会创建副本。)
Joshua Goldberg

4
@Notinlist Java家伙也想到了这一点。使用Arrays.toList(list).sublist(from,to).indexOf(o)搜索范围内的元素[from, to)
马里奥·卡内罗

62

数组没有indexOf()方法。

也许ArrayUtils您正在寻找这种Apache Commons Lang 方法

import org.apache.commons.lang3.ArrayUtils;

String[] colours = { "Red", "Orange", "Yellow", "Green" };

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");

Eclipse找不到此导入库。
奥莫尔

21

对于基元,如果要避免装箱,Guava提供了基元数组的帮助器,例如Ints.indexOf(int []数组,int目标)


其他解决方案都创建新的字符串或列表,或者仅处理单个元素。Guava的Chars.indexOf可让您获取数组中数组的索引。这是正确的解决方案。
HappyEngineer '16

18

空无一人。java.util.List您可以使用*,也可以编写自己的代码indexOf()

public static <T> int indexOf(T needle, T[] haystack)
{
    for (int i=0; i<haystack.length; i++)
    {
        if (haystack[i] != null && haystack[i].equals(needle)
            || needle == null && haystack[i] == null) return i;
    }

    return -1;
}

*您可以使用以下方法从阵列中制作一个 Arrays#asList()


2
使用T具有误导性。它不提供任何类型安全性,很容易出错,它是类型安全性...更好地使用对象
Venkata Raju 2014年

4
@VenkataRaju,此处使用T强制两个方法参数为同一类型。这很有用。
gonadarian 2015年

5
@gonadarian不是。这两种编译就好了:indexOf("str", new Object[] {});indexOf(new Object(), new String[] {});
文卡塔拉朱

1
@VenkataRaju是的。由于字符串是一个对象,因此您的示例没有任何内容。因此,很明显,对象数组可以包含您可能要查找其索引的字符串。

1
@ ghert85又如:indexOf("str", new Date[] {})indexOf(new Date(), new String[] {})
文卡塔拉朱

15

不像在C#中,你必须在Array.IndexOf方法,和JavaScript,你必须在的indexOf方法,Java的API(中ArrayArrays尤其是类)没有这种方法。

此方法indexOf(及其补充lastIndexOf)在java.util.List接口中定义。请注意,indexOf和lastIndexOf不会重载,仅将Object作为参数。

如果对数组进行排序,则很幸运,因为Arrays类定义了binarySearch方法的一系列重载,它们将以最佳性能找到要查找的元素的索引(O(log n)而不是O(n ),您可以从indexOf)进行的顺序搜索中看到后者。有四个注意事项:

  1. 数组必须按照自然顺序或您作为参数提供的Comparator的顺序进行排序,或者至少所有“小于”键的元素必须排在数组中的该元素之前以及所有“大于”键必须位于数组中的该元素之后;

  2. 通常使用indexOf进行的测试,以确定键是否在数组中(验证返回值是否为-1)不适合binarySearch。您需要验证返回值是否不小于零,因为返回的值将表明该键不存在,但指示该键存在(如果存在的话)。

  3. 如果您的数组包含多个等于键的元素,则从binarySearch获得的内容是不确定的;这不同于indexOf将返回第一个匹配项,而lastIndexOf将返回最后一个匹配项。

  4. 如果布尔数组首先包含所有false,然后包含所有true,则可能会被排序,但这并不算在内。没有覆盖接受布尔数组的binarySearch方法的覆盖,并且如果要在检测第一个true出现在数组中的位置时想要O(log n)性能,则必须在此处做一些聪明的事情,例如使用布尔值和常量Boolean.FALSE和Boolean.TRUE。

如果数组未排序且不是原始类型,则可以通过调用java.util.Arrays 的asList方法来使用List的indexOf和lastIndexOf方法。此方法将返回数组周围的AbstractList接口包装器。因为它不创建阵列的副本,所以它涉及的开销最小。如前所述,此方法不会重载,因此仅适用于引用类型的数组。

如果您的数组未排序,并且数组的类型原始数组,那么Java API会让您不走运。编写您自己的for循环或您自己的静态实用程序方法,这肯定会优于asList方法的性能优势,后者涉及对象实例化的一些开销。如果您担心编写循环遍历数组所有元素的蛮力循环不是一个优雅的解决方案,请接受那确实是Java API在调用indexOf时所做的事情。您可以进行如下操作:

public static int indexOfIntArray(int[] array, int key) {
    int returnvalue = -1;
    for (int i = 0; i < array.length; ++i) {
        if (key == array[i]) {
            returnvalue = i;
            break;
        }
    }
    return returnvalue;
}

如果要避免在此处编写自己的方法,请考虑使用像Guava这样的开发框架中的方法。在那里,您可以找到indexOflastIndexOf的实现。



6

除了为自己编写代码外,我不记得在数组上使用“ indexOf”了……虽然如果您的数组包含原始类型,则可以使用许多java.util.Arrays#binarySearch(...)方法之一(请参阅Arrays javadoc


5

List接口具有indexOf()方法,您可以使用Array的asList()方法从数组中获取List。除此之外,Array本身没有这种方法。它确实具有用于排序数组的binarySearch()方法。


4

数组本身没有该方法。但是,列表可以: indexOf


2
不只是ArrayList-每个Java List都有indexOf()
马特·鲍尔

是的,我只是指定了ArrayList,因为这可能是OP所寻找的最接近的东西:)
Igor,



0

杰弗里·汉汀()的回答是好的,但它有一定的局限性(如果这样做或不这样做)。

您可以编写自己的扩展方法,并且该方法始终以所需的方式工作。

Lists.indexOf(array, x -> item == x); // compare in the way you want

这是你的扩展名

public final class Lists {
    private Lists() {
    }

    public static <T> int indexOf(T[] array, Predicate<T> predicate) {
        for (int i = 0; i < array.length; i++) {
            if (predicate.test(array[i])) return i;
        }
        return -1;
    }

    public static <T> int indexOf(List<T> list, Predicate<T> predicate) {
        for (int i = 0; i < list.size(); i++) {
            if (predicate.test(list.get(i))) return i;
        }
        return -1;
    }

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

-4
int findIndex(int myElement, int[] someArray){
 int index = 0;
 for(int n: someArray){
   if(myElement == n) return index;
   else index++;
 }
}

注意:您可以将此方法用于int类型的数组,也可以将该算法用于具有较小更改的其他类型


1
-1:首先,这会使我们可能不想要的要排序的原始数组发生变化。其次,它为答案提供了排序后的数组,而不是我们可能想要的原始数组(如果我们想要答案为排序后的数组,那么它将已经被排序)。第三,由于排序是O(n log n),这比线性地遍历数组要慢。因此,这个答案既错误又无效。
杰米

使用就地排序时,原始索引丢失。
Downhillski
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.