Mảng indexOf của Java ở đâu?


198

Tôi phải thiếu một cái gì đó rất rõ ràng, nhưng tôi đã tìm kiếm khắp nơi và không thể tìm thấy phương pháp này.

Câu trả lời:


234

Có một vài cách để thực hiện điều này bằng cách sử dụng Arrayslớp tiện ích.

Nếu mảng không được sắp xếp và không phải là mảng nguyên thủy:

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

Nếu mảng nguyên thủy và không được sắp xếp, người ta nên sử dụng một giải pháp được cung cấp bởi một trong những câu trả lời khác như của Kerem Baydoğan , Andrew McKinlay hoặc Mishax . Đoạn mã trên sẽ biên dịch ngay cả khi theArraylà nguyên thủy (có thể phát ra cảnh báo) nhưng dù sao bạn cũng sẽ nhận được kết quả hoàn toàn không chính xác.

Nếu mảng được sắp xếp, bạn có thể sử dụng tìm kiếm nhị phân cho hiệu suất:

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

3
Tôi khá chắc chắn rằng câu trả lời này ít nhất là sai đối với java 1.6: download.oracle.com/javase/6/docs/api/java/util/ù asList biến danh sách các đối số thành một danh sách không phải là chính đối số.
Alexandru

11
@Alexandru Xử lý Ellipsis là đường cú pháp. Nếu bạn có một đối số được nhập T..., loại thời gian chạy thực tế của đối số là T[]và truyền 0 hoặc nhiều tham số loại Tkết quả trong đó chúng được gói vào một mảng được xây dựng mới và được thông qua. Nếu tham số được truyền đã là loại T[], đường cú pháp được bỏ qua.
Jeffrey Hantin

7
Tôi thấy điểm của bạn. Tuy nhiên, giải pháp ( .indexOf) không hợp lệ đối với nguyên thủy.
Alexandru

53
Vì không ai đề cập: Arrays.asList sử dụng mảng đã tồn tại làm chỗ dựa. (Tức là không có lo ngại về một bản sao được tạo ra.)
Joshua Goldberg

4
@Notinlist Các anh chàng java cũng nghĩ thế. Sử dụng Arrays.toList(list).sublist(from,to).indexOf(o)để tìm kiếm một yếu tố trong phạm vi [from, to).
Mario Carneiro

62

Mảng không có indexOf()phương thức.

Có lẽ ArrayUtilsphương thức Apache Commons Lang này là những gì bạn đang tìm kiếm

import org.apache.commons.lang3.ArrayUtils;

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

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

Eclipse không tìm thấy thư viện nhập khẩu này.
Omore

21

Đối với người nguyên thủy, nếu bạn muốn tránh quyền anh, Guava có người trợ giúp cho mảng nguyên thủy, ví dụ như Ints.indexOf (int [] mảng, int target)


Các giải pháp khác đều tạo ra các chuỗi hoặc danh sách mới hoặc chỉ xử lý các phần tử đơn lẻ. Chava.indexOf của Guava cho phép bạn lấy chỉ mục của một mảng trong một mảng. Đây là giải pháp chính xác.
HappyEngineer

18

Chẳng có ai. Sử dụng dấu java.util.List* hoặc bạn có thể tự viết 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;
}

* bạn có thể tạo một từ mảng của mình bằng cách sử dụng Arrays#asList()


2
Sử dụng Tlà sai lệch. Nó không cung cấp bất kỳ loại an toàn nào, dễ nhầm là loại an toàn ... sử dụng tốt hơn Object
Venkata Raju

4
@VenkataRaju, sử dụng T ở đây buộc cả hai tham số phương thức phải cùng loại. Điều đó hữu ích.
gonadarian

5
@gonadarian Không thực sự. Cả hai biên dịch này đều ổn : indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju

1
@VenkataRaju Vâng thực sự. Ví dụ của bạn không chứng minh bất cứ điều gì vì Chuỗi là Đối tượng ... vì vậy rõ ràng một mảng Đối tượng có thể chứa Chuỗi mà bạn có thể muốn tìm chỉ mục của.

1
@ ghert85 Một ví dụ khác : indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju

15

Không giống như trong C #, nơi bạn có Array.IndexOf phương pháp, và JavaScript, nơi bạn có indexOf phương pháp, API của Java (các ArrayArrayscác lớp học đặc biệt) không có phương pháp như vậy.

Phương thức indexOf này (cùng với phần bổ sung last IndexOf) được định nghĩa trong giao diện java.util.List . Lưu ý rằng indexOf và lastIndexOf không bị quá tải và chỉ lấy một đối tượng làm tham số.

Nếu mảng của bạn được sắp xếp , bạn sẽ gặp may vì lớp Arrays định nghĩa một loạt các tình trạng quá tải của phương thức binarySearch sẽ tìm chỉ mục của phần tử bạn đang tìm kiếm với hiệu suất tốt nhất có thể (O (log n) thay vì O (n ), thứ hai là những gì bạn có thể mong đợi từ một tìm kiếm tuần tự được thực hiện bởi indexOf). Có bốn cân nhắc:

  1. Mảng phải được sắp xếp theo thứ tự tự nhiên hoặc theo thứ tự của Bộ so sánh mà bạn cung cấp làm đối số hoặc ít nhất là tất cả các phần tử "nhỏ hơn" khóa phải đến trước phần tử đó trong mảng và tất cả các phần tử là "lớn hơn" khóa phải đến sau phần tử đó trong mảng;

  2. Kiểm tra mà bạn thường làm với indexOf để xác định xem một khóa có nằm trong mảng không (xác minh nếu giá trị trả về không -1) không giữ với binarySearch. Bạn cần xác minh rằng giá trị trả về không nhỏ hơn 0 vì giá trị được trả về sẽ cho biết khóa không có mặt nhưng chỉ số mà nó sẽ được mong đợi nếu nó tồn tại;

  3. Nếu mảng của bạn chứa nhiều phần tử bằng với khóa, những gì bạn nhận được từ binarySearch sẽ không được xác định; điều này khác với indexOf sẽ trả về lần xuất hiện đầu tiên và lần cuối IndexOf sẽ trả về lần xuất hiện cuối cùng.

  4. Một mảng các booleans có thể được sắp xếp nếu nó đầu tiên chứa tất cả các lỗi và sau đó là tất cả các dấu vết, nhưng điều này không được tính. Không có ghi đè phương thức binarySearch chấp nhận một mảng booleans và bạn sẽ phải làm điều gì đó thông minh ở đó nếu bạn muốn hiệu suất O (log n) khi phát hiện nơi đúng đầu tiên xuất hiện trong một mảng, ví dụ như sử dụng một mảng Booleans và các hằng số Boolean.FALSE và Boolean.TRUE.

Nếu mảng của bạn không được sắp xếp và không phải kiểu nguyên thủy , bạn có thể sử dụng các phương thức indexOf và last IndexOf của List bằng cách gọi phương thức asList của java.util.Arrays. Phương thức này sẽ trả về một trình bao bọc giao diện AbstractList xung quanh mảng của bạn. Nó liên quan đến chi phí tối thiểu vì nó không tạo ra một bản sao của mảng. Như đã đề cập, phương pháp này không bị quá tải nên điều này sẽ chỉ hoạt động trên các mảng của các loại tham chiếu.

Nếu mảng của bạn không được sắp xếp và loại của mảng nguyên thủy , bạn sẽ không gặp may với API Java. Viết vòng lặp của riêng bạn hoặc phương thức tiện ích tĩnh của riêng bạn, chắc chắn sẽ có lợi thế về hiệu suất so với cách tiếp cận asList liên quan đến một số chi phí của việc khởi tạo đối tượng. Trong trường hợp bạn lo ngại rằng việc viết một lực mạnh mẽ cho vòng lặp lặp trên tất cả các phần tử của mảng không phải là một giải pháp tao nhã, hãy chấp nhận rằng đó chính xác là những gì API Java đang làm khi bạn gọi indexOf. Bạn có thể làm một cái gì đó như thế này:

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;
}

Nếu bạn muốn tránh viết phương pháp của riêng mình ở đây, hãy xem xét sử dụng một phương pháp từ khung phát triển như Guava. Ở đó bạn có thể tìm thấy việc triển khai indexOflastIndexOf .


11

Java ArrayListcó một indexOfphương thức. Mảng Java không có phương thức như vậy.


26
Không chỉ ArrayList- mọi Java Listđều có indexOf().
Matt Ball

6

Tôi không nhớ lại "indexOf" trên các mảng khác ngoài việc tự mã hóa nó ... mặc dù bạn có thể sử dụng một trong nhiều java.util.Arrays#binarySearch(...)phương thức (xem Arrays javadoc ) nếu mảng của bạn chứa các kiểu nguyên thủy


5

Giao diện Danh sách có phương thức indexOf () và bạn có thể lấy Danh sách từ mảng của mình bằng phương thức asList () của Array. Ngoài ra, bản thân Array không có phương thức như vậy. Nó có một phương thức binarySearch () cho các mảng được sắp xếp.


4

Bản thân mảng không có phương pháp đó. Danh sách, tuy nhiên, không: indexOf


2
Không chỉ ArrayList- mọi Java Listđều có indexOf().
Matt Ball

Vâng, tôi chỉ chỉ định ArrayList vì đó có thể là thứ gần nhất với những gì OP đang tìm kiếm :)
Igor


2

Không có chức năng indexOf trực tiếp trong mảng java.


0

Câu trả lời của Jeffrey Hantin là tốt nhưng nó có một số hạn chế, nếu điều này làm điều này hay cách khác ...

Bạn có thể viết phương thức mở rộng của riêng bạn và nó luôn hoạt động theo cách bạn muốn.

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

Và đây là phần mở rộng của bạn

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++;
 }
}

Lưu ý: bạn có thể sử dụng phương thức này cho các mảng kiểu int, bạn cũng có thể sử dụng thuật toán này cho các loại khác với những thay đổi nhỏ


1
-1: Đầu tiên, điều này làm thay đổi mảng ban đầu được sắp xếp mà chúng ta có thể không muốn. Thứ hai, nó đưa ra câu trả lời wrt mảng được sắp xếp, không phải là mảng ban đầu có khả năng là những gì chúng ta muốn (nếu chúng ta muốn câu trả lời wrt mảng đã sắp xếp, nó sẽ được sắp xếp). Thứ ba vì sắp xếp là O (n log n) nên việc này chậm hơn so với việc chỉ đi qua mảng một cách tuyến tính. Vì vậy, câu trả lời này là sai và không hiệu quả.
Jamie

chỉ mục ban đầu bị mất khi sử dụng sắp xếp tại chỗ.
Downhillski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.