Java ตรวจสอบแบบง่ายว่า int array มี int หรือไม่


98

โดยทั่วไปเพื่อนของฉันบอกว่าฉันสามารถทำให้โค้ดสั้นลงได้โดยใช้วิธีอื่นในการตรวจสอบว่าอาร์เรย์ int มี int หรือไม่แม้ว่าเขาจะไม่บอกฉันว่ามันคืออะไร: P

ปัจจุบัน:

public boolean contains(final int[] array, final int key) {
    for (final int i : array) {
        if (i == key) {
            return true;
        }
    }
    return false;
}

ลองใช้สิ่งนี้ด้วยแม้ว่ามันจะส่งคืนเท็จเสมอด้วยเหตุผลบางประการ

public boolean contains(final int[] array, final int key) {
    return Arrays.asList(array).contains(key);
}

มีใครช่วยฉันได้ไหม

ขอขอบคุณ.


8
การเรียก Arrays.asList (... ) ของคุณใช้ vararg นั่นคือมันจะรวมอาร์กิวเมนต์ตามจำนวนที่คุณอาจส่งผ่านเข้าไปในรายการ ในกรณีของคุณคุณจะได้รับรายการอาร์เรย์ที่มีองค์ประกอบเดียวและเห็นได้ชัดว่ารายการนี้ไม่มี int
sarcan

ความคิดเห็นของคุณหมายถึงอะไรตอนนี้?
sarcan

ตรวจสอบHashsetคำตอบตามกลไกการพิจารณาคดี เป็นวิธีที่เร็วที่สุด
Amit Deshpande

ฉันไม่เห็นจุดใดในการทำให้โค้ดดั้งเดิมของคุณสั้นลงเนื่องจากอาร์กิวเมนต์ของคุณเป็นอาร์เรย์แบบดั้งเดิมและโค้ดของคุณชัดเจนและตรงไปตรงมามาก ArrayListการใช้งานก็ทำเช่นเดียวกัน
Genzer

ฉันจะไม่ทำให้รหัสของคุณสั้นลง (1) arraylist ทำสิ่งเดียวกับที่คุณทำ (2) - สิ่งที่สำคัญกว่าคือการย่อโค้ดโดยใช้ Arrays.asList สร้างออบเจ็กต์ใหม่ซึ่งอาจเป็นปัญหาภายในโค้ดที่สำคัญของประสิทธิภาพ ข้อมูลโค้ดแรกเป็นสิ่งที่ดีที่สุดที่คุณทำได้
Martin Podval

คำตอบ:



67

คุณสามารถใช้ArrayUtils.containsจากApache Commons Lang library.

public boolean contains(final int[] array, final int key) {     
    return ArrayUtils.contains(array, key);
}

1
ตราบเท่าที่คุณใช้ ArrayUtils มีเหตุผลใดบ้างที่จะไม่ใช้ArrayUtils.contains
mjohnsonengr

2
ไม่มีเหตุผลใด ๆ :)
Reimeus

21
เป็นที่น่าสังเกตว่าArrayUtils.contains()เป็นส่วนหนึ่งของApache Commons Langห้องสมุด แม้ว่าจะเป็น lib ที่ยอดเยี่ยม แต่ก็อาจไม่ใช่ความคิดที่ดีที่จะเพิ่มการพึ่งพาภายนอกเพียงเพื่อตรวจสอบว่าอาร์เรย์มีองค์ประกอบหรือไม่: D
Krzysiek

2
ArrayUtils เป็นอดีตไปแล้ว Java 8+ และ Guava มีของดีที่น่าทึ่ง !!
TriCore

35

มันเป็นเพราะผลตอบแทนArrays.asList(array) อาร์กิวเมนต์จะถือว่าเป็นค่าเดียวที่คุณต้องการตัด (คุณจะได้รับรายการอาร์เรย์ของ ints) ไม่ใช่เป็น varargList<int[]>array

หมายเหตุว่ามันจะทำงานร่วมกับวัตถุประเภท (ไม่ primitives):

public boolean contains(final String[] array, final String key) {
    return Arrays.asList(array).contains(key);
}

หรือแม้กระทั่ง:

public <T>  boolean contains(final T[] array, final T key) {
    return Arrays.asList(array).contains(key);
}

แต่คุณไม่สามารถมีได้List<int>และการทำกล่องอัตโนมัติไม่ทำงานที่นี่


1
เหตุใดการทำ autoboxing จึงไม่ทำงานเป็นเพราะมีการประกาศให้เป็นที่สิ้นสุดหรือไม่?
subhashis

20

ฝรั่งเสนอวิธีเสริมประเภทดึกดำบรรพ์ ในหมู่พวกเขามีวิธีการที่ใช้อาร์กิวเมนต์เดียวกับของคุณ

public boolean contains(final int[] array, final int key) {
    return Ints.contains(array, key);
}

คุณอาจนำเข้าเวอร์ชัน guava แบบคงที่ได้เช่นกัน

ดูคำอธิบายของ Guava Primitives


18

วิธีอื่น:

public boolean contains(final int[] array, final int key) {  
     Arrays.sort(array);  
     return Arrays.binarySearch(array, key) >= 0;  
}  

สิ่งนี้ปรับเปลี่ยนอาร์เรย์ที่ส่งผ่าน คุณจะมีตัวเลือกในการคัดลอกอาร์เรย์และทำงานกับอาร์เรย์เดิมเช่นint[] sorted = array.clone();
แต่นี่เป็นเพียงตัวอย่างของโค้ดสั้น ๆ รันไทม์อยู่O(NlogN)ในขณะที่คุณอยู่O(N)


30
ฉันคิดว่าฉันจะแปลกใจถ้าcontainsวิธีการแก้ไขอาร์เรย์ของฉัน
Zong

@ZongLi: นี่เป็นเพียงตัวอย่างสำหรับ OP เท่านั้นอัปเดต OP ถ้าเรากำลัง nitpicking
Cratylus

5
จาก javadoc ของ binarySearch (): "ค่าที่ส่งคืนจะเป็น> = 0 หากพบคีย์เท่านั้น" ดังนั้น Arrays.binarySearch (อาร์เรย์, คีย์)> = 0 ควรส่งคืน!
icza

Supplement: ค่าส่งคืนของ binarySearch () คือ (- (จุดแทรก) - 1) หากไม่มีคีย์ซึ่งอาจเป็นค่าอื่นที่ไม่ใช่ -1
icza

สิ่งนี้ไม่สามารถเกิดขึ้นได้-1หากตั้งใจให้เป็นจริง "จุดแทรกถูกกำหนดให้เป็นจุดที่จะแทรกคีย์ลงในรายการ: ดัชนีขององค์ประกอบแรกมากกว่าคีย์หรือ list.size () หากองค์ประกอบทั้งหมดในรายการมีค่าน้อยกว่าคีย์ที่ระบุ ". ต้องบอกว่า>= 0.
Brian


2

คุณสามารถแปลงอาร์เรย์ int ดั้งเดิมของคุณเป็นอาร์เรย์ของจำนวนเต็มโดยใช้โค้ด Java 8 ด้านล่าง

List<Integer> arrayElementsList = Arrays.stream(yourArray).boxed().collect(Collectors.toList());

จากนั้นใช้contains()วิธีตรวจสอบว่ารายการมีองค์ประกอบเฉพาะหรือไม่

boolean containsElement = arrayElementsList.contains(key);

1

1. การใช้งานเพียงครั้งเดียว

List<T> list=Arrays.asList(...)
list.contains(...)

2. ใช้ HashSet เพื่อพิจารณาประสิทธิภาพหากคุณใช้มากกว่าหนึ่งครั้ง

Set <T>set =new HashSet<T>(Arrays.asList(...));
set.contains(...)

1

ลองสิ่งนี้:

public static void arrayContains(){
    int myArray[]={2,2,5,4,8};

    int length=myArray.length;

    int toFind = 5;
    boolean found = false;

    for(int i = 0; i < length; i++) {
        if(myArray[i]==toFind) {
            found=true;
        }
    }

    System.out.println(myArray.length);
    System.out.println(found); 
}

0

สิ่งนี้ใช้ได้ใน java 8

public static boolean contains(final int[] array, final int key)
{
return Arrays.stream(array).anyMatch(n->n==key);
}

ควรกลับมาในการแข่งขันครั้งแรกทันที แต่จะยังคงสแกนรายการทั้งหมดในอาร์เรย์แม้ว่าจะพบรายการที่ตรงกันก็ตาม (พิจารณาอาร์เรย์ของรายการ trilion)
TriCore

คุณลองใช้บูลีนแบบคงที่สาธารณะนี้มี (อาร์เรย์ int [] สุดท้าย, คีย์ int สุดท้าย) {return Arrays.stream (array) .anyMatch (n-> n == คีย์); }
Farhad Baghirov

Java 8 stream anyMatch เป็นการดำเนินการลัดวงจรและจะไม่สแกนรายการทั้งหมดในอาร์เรย์
LordParsley

@LordParsley เป้าหมายของโค้ดด้านบนคือตรวจสอบองค์ประกอบในอาร์เรย์ไม่ใช่สแกนองค์ประกอบทั้งหมดของอาร์เรย์
Farhad Baghirov

ขออภัยฉันเห็นว่าคำตอบถูกแก้ไข ฉันแค่ย้ำว่ามันถูกต้องเพราะไม่จำเป็นต้องสแกนทั้งหมดหากพบเพียงส่วนเดียว
LordParsley


-1

ขึ้นอยู่กับว่าอาร์เรย์ของ int ของคุณมีขนาดใหญ่เพียงใดคุณจะได้รับประสิทธิภาพที่ดีขึ้นมากหากคุณใช้คอลเลกชันและ.containsแทนที่จะทำซ้ำในอาร์เรย์ทีละองค์ประกอบ:

import static org.junit.Assert.assertTrue;
import java.util.HashSet;

import org.junit.Before;
import org.junit.Test;

public class IntLookupTest {

int numberOfInts = 500000;
int toFind = 200000;
int[] array;

HashSet<Integer> intSet;

@Before
public void initializeArrayAndSet() {
    array = new int[numberOfInts];
    intSet = new HashSet<Integer>();
    for(int i = 0; i < numberOfInts; i++) {
        array[i] = i;
        intSet.add(i);
    }
}

@Test
public void lookupUsingCollections() {
    assertTrue(intSet.contains(toFind));
}

@Test
public void iterateArray() {
    assertTrue(contains(array, toFind));

}

public boolean contains(final int[] array, final int key) {
    for (final int i : array) {
        if (i == key) {
            return true;
        }
    }
    return false;
}
}

-1

โซลูชัน # 1

เนื่องจากคำถามเดิมต้องการเพียงวิธีแก้ปัญหาที่เรียบง่าย (ไม่ใช่คำถามที่เร็วกว่า) นี่คือคำตอบแบบบรรทัดเดียว

public boolean contains(int[] array, int key) {
    return Arrays.toString(array).matches(".*[\\[ ]" + key + "[\\],].*");
}

คำอธิบาย: Javadoc ของArrays.toString()สถานะผลลัพธ์จะอยู่ในวงเล็บเหลี่ยมและองค์ประกอบที่อยู่ติดกันจะถูกคั่นด้วยอักขระ "," (เครื่องหมายจุลภาคตามด้วยช่องว่าง) เราจึงสามารถนับสิ่งนี้ได้ ก่อนอื่นเราแปลงarrayเป็นสตริงจากนั้นตรวจสอบว่าkeyมีอยู่ในสตริงนี้หรือไม่ แน่นอนว่าเราไม่สามารถยอมรับ "ตัวเลขย่อย" ได้ (เช่น "1234" มี "23") ดังนั้นเราต้องมองหารูปแบบที่keyนำหน้าด้วยวงเล็บเปิดหรือช่องว่างและตามด้วยวงเล็บปิดหรือลูกน้ำ

หมายเหตุ:รูปแบบ regexp ที่ใช้ยังจัดการกับตัวเลขเชิงลบอย่างเหมาะสม (ซึ่งการแทนค่าสตริงเริ่มต้นด้วยเครื่องหมายลบ)

โซลูชัน # 2

มีการโพสต์โซลูชันนี้แล้ว แต่มีข้อผิดพลาดดังนั้นฉันจึงโพสต์วิธีแก้ไขที่ถูกต้อง:

public boolean contains(int[] array, int key) {
    Arrays.sort(array);
    return Arrays.binarySearch(array, key) >= 0;
}

นอกจากนี้วิธีการแก้ปัญหานี้ยังมีผลข้างเคียง: มันปรับเปลี่ยนarray(เรียงลำดับ)


สตริง Handlig โดยทั่วไปมีราคาแพงเหตุใดบางคนจึงถือว่า ints เป็นสตริง
Denys Vitali

@DenysVitali เนื่องจาก op มีโซลูชันที่ใช้งานได้และมีประสิทธิภาพอยู่แล้วและเขากำลังมองหาทางออกที่สั้นกว่า และสิ่งเหล่านี้จะสั้นกว่า คำถามนี้ไม่เกี่ยวกับประสิทธิภาพ
icza

ฉันน่าจะเข้าใจคำถามผิดแล้วขอโทษที่ถาม
Denys Vitali

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.