java - अगर किसी सरणी में एक निश्चित मान होता है तो मैं परीक्षण कैसे कर सकता हूं?




arrays (16)

मेरे पास एक String[] तरह के मानों के साथ:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

दिए गए String s , क्या परीक्षण करने का एक अच्छा तरीका है कि VALUES में क्या है?


  1. सीमित लंबाई के सरणी के लिए निम्नलिखित का उपयोग करें (जैसा कि कैमिकर द्वारा दिया गया है)। यह बार-बार जांच के लिए धीमा है, खासकर लंबे सरणी (रैखिक खोज) के लिए।

     Arrays.asList(...).contains(...)
    
  2. तेजी से प्रदर्शन के लिए यदि आप बार-बार तत्वों के एक बड़े समूह के खिलाफ जांच करते हैं

    • एक सरणी गलत संरचना है। TreeSet प्रयोग करें और इसमें प्रत्येक तत्व जोड़ें। यह तत्वों का प्रकार है और एक तेज़ exist() विधि (बाइनरी खोज) है।

    • यदि तत्व Comparable लागू करते हैं और आप TreeSet तदनुसार क्रमबद्ध करना चाहते हैं:

      ElementClass.compareTo() विधि ElementClass.compareTo() के साथ संगत होना चाहिए: ElementClass.equals() को लड़ने के लिए दिखाई नहीं दे रहा है? (जावा सेट एक आइटम गायब है)

      TreeSet myElements = new TreeSet();
      
      // Do this for each element (implementing *Comparable*)
      myElements.add(nextElement);
      
      // *Alternatively*, if an array is forceably provided from other code:
      myElements.addAll(Arrays.asList(myArray));
      
    • अन्यथा, अपने स्वयं के Comparator उपयोग करें:

      class MyComparator implements Comparator<ElementClass> {
           int compareTo(ElementClass element1; ElementClass element2) {
                // Your comparison of elements
                // Should be consistent with object equality
           }
      
           boolean equals(Object otherComparator) {
                // Your equality of comparators
           }
      }
      
      
      // construct TreeSet with the comparator
      TreeSet myElements = new TreeSet(new MyComparator());
      
      // Do this for each element (implementing *Comparable*)
      myElements.add(nextElement);
      
    • भुगतान: कुछ तत्व के अस्तित्व की जांच करें:

      // Fast binary search through sorted elements (performance ~ log(size)):
      boolean containsElement = myElements.exists(someElement);
      

Arrays.asList => तब शामिल है () विधि हमेशा काम करेगी, लेकिन खोज एल्गोरिदम पहले से बहुत बेहतर है, आपको ऐरे को एक सूची में परिवर्तित करना होगा, फिर उस विधि को कॉल करना होगा, ओवरहेड को दोगुना करना होगा, देखें कि मेरा क्या मतलब है ? ऐसा इसलिए है क्योंकि यह अनुक्रमिक जांच के माध्यम से तत्व खोजने के लिए सूची और ओ (एन) बनाने के लिए ओ (एन) है। ओ (एन) दो बार क्यों पीड़ित है जब एक साधारण रैखिक खोज केवल एक बार नौकरी करता है।

public boolean findString(String[] strings, String desired){
   for(String s : strings){
       if (desired.equals(s)){
           return true;
       }
   }
   return false; //if we get here… there is no desired String, return false.
}

असल में, यदि आप हैशसेट का उपयोग टॉम हौटिन के रूप में करते हैं तो आपको सॉर्टिंग के बारे में चिंता करने की आवश्यकता नहीं है और आपकी गति एक पूर्ववर्ती सरणी पर बाइनरी खोज के समान ही है, शायद तेज़ भी।

यह सब इस बात पर निर्भर करता है कि आपका कोड कैसे स्थापित किया गया है, जाहिर है, लेकिन जहां से मैं खड़ा हूं, आदेश होगा:

एक संयुक्त राष्ट्र सरणी पर:

  1. HashSet
  2. asList
  3. सॉर्ट और बाइनरी

एक क्रमबद्ध सरणी पर:

  1. HashSet
  2. बाइनरी
  3. asList

तो किसी भी तरह से, हैशसेट ftw


आप Apache Commons Lang से ArrayUtils.contains उपयोग कर सकते हैं

public static boolean contains(Object[] array, Object objectToFind)

ध्यान दें कि पारित सरणी null यह विधि false है।

सभी प्रकार के आदिम सरणी के लिए भी विधियां उपलब्ध हैं।

उदाहरण:

String[] fieldsToInclude = { "id", "name", "location" };

if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
    // Do some stuff.
}

आपके लिए त्वरित सरणी प्रारंभिक वाक्यविन्यास का उपयोग करने के बजाय Arrays.asList विधि का उपयोग कर इसे सीधे उसी तरह से सूची के रूप में प्रारंभ कर सकते हैं जैसे:

public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");

फिर आप कर सकते हैं (ऊपर की तरह): STRINGS.contains("the string you want to find");


इसके लायक होने के लिए मैंने गति के लिए 3 सुझावों की तुलना में एक परीक्षण चलाया। मैंने यादृच्छिक पूर्णांक उत्पन्न किए, उन्हें एक स्ट्रिंग में परिवर्तित कर दिया और उन्हें एक सरणी में जोड़ा। इसके बाद मैंने उच्चतम संभावित संख्या / स्ट्रिंग की खोज की, जो कि asist () के लिए सबसे खराब स्थिति परिदृश्य होगा। ()।

10 के सरणी आकार का उपयोग करते समय परिणाम कहां:

Sort & Search   : 15
Binary Search   : 0
asList.contains : 0

एक 100 के सरणी का उपयोग करते समय परिणाम जहां:

Sort & Search   : 156
Binary Search   : 0
asList.contains : 32

तो यदि सरणी क्रमबद्ध क्रम में बनाई गई है तो द्विआधारी खोज सबसे तेज़ है, अन्यथा asList ()। इसमें जाने का तरीका होगा। यदि आपके पास कई खोज हैं, तो सरणी को सॉर्ट करना उचित हो सकता है ताकि आप बाइनरी खोज का उपयोग कर सकें। यह सब आपके आवेदन पर निर्भर करता है।

मुझे लगता है कि वे परिणाम हैं जो अधिकतर लोग उम्मीद करेंगे। टेस्ट कोड यहां दिया गया है:

import java.util.*;

public class Test
{
    public static void main(String args[])
    {
        long start = 0;
        int size = 100000;
        String[] strings = new String[size];
        Random random = new Random();


        for (int i = 0; i < size; i++)
            strings[i] = "" + random.nextInt( size );

        start = System.currentTimeMillis();
        Arrays.sort(strings);
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1) ));
        System.out.println("Sort & Search : " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1) ));
        System.out.println("Search        : " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.asList(strings).contains( "" + (size - 1) ));
        System.out.println("Contains      : " + (System.currentTimeMillis() - start));
    }
}

इसे देखो

String[] VALUES = new String[] {"AB","BC","CD","AE"};
String s;

for(int i=0; i< VALUES.length ; i++)
{
    if ( VALUES[i].equals(s) )
    { 
        // do your stuff
    } 
    else{    
        //do your stuff
    }
}

एक संभावित समाधान:

import java.util.Arrays;
import java.util.List;

public class ArrayContainsElement {
  public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");

  public static void main(String args[]) {

      if (VALUES.contains("AB")) {
          System.out.println("Contains");
      } else {
          System.out.println("Not contains");
      }
  }
}

जावा 8 के साथ आप एक स्ट्रीम बना सकते हैं और जांच सकते हैं कि स्ट्रीम में कोई प्रविष्टियां "s" मेल खाती हैं या नहीं:

String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);

या एक सामान्य विधि के रूप में:

public static <T> boolean arrayContains(T[] array, T value) {
    return Arrays.stream(array).anyMatch(value::equals);
}

डेवलपर्स अक्सर करते हैं:

Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

उपर्युक्त कोड काम करता है, लेकिन सूची को पहले सेट करने के लिए कनवर्ट करने की आवश्यकता नहीं है। एक सूची में एक सूची को कनवर्ट करने के लिए अतिरिक्त समय की आवश्यकता होती है। यह उतना आसान हो सकता है:

Arrays.asList(arr).contains(targetValue);

या

   for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }

return false;

पहला एक दूसरे की तुलना में अधिक पठनीय है।


बस शुरू करने के लिए कोड को साफ़ करने के लिए। हमने (सही) किया है:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

यह एक परिवर्तनीय स्थैतिक है जो FindBugs आपको बताएगा कि आप बहुत शरारती हैं। यह निजी होना चाहिए:

private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

(ध्यान दें, आप वास्तव में new String[]; बिट छोड़ सकते हैं।)

तो, संदर्भ सरणी खराब हैं, और विशेष रूप से यहां हम एक सेट चाहते हैं:

private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
     new String[] {"AB","BC","CD","AE"}
));

(पारानोइड लोग, जैसे कि खुद, आसानी से अधिक महसूस कर सकते हैं अगर यह Collections.unmodifiableSet .unmodifiableSet में लपेटा गया था - इसे भी सार्वजनिक किया जा सकता है।)

"दिए गए स्ट्रिंग एस, क्या परीक्षण करने का एक अच्छा तरीका है कि मूल्यों में क्या है?"

VALUES.contains(s)

हे (1)।


मुझे आश्चर्य है कि किसी ने इसे हाथ से लागू करने का सुझाव नहीं दिया है:

public static <T> boolean contains(final T[] array, final T v) {
    for (final T e : array)
        if (e == v || v != null && v.equals(e))
            return true;

    return false;
}

सुधार की:

v != null स्थिति विधि के अंदर स्थिर है, यह हमेशा विधि कॉल के दौरान उसी बूलियन मान का मूल्यांकन करती है। इसलिए यदि इनपुट array बड़ी है, तो यह केवल एक बार इस स्थिति का मूल्यांकन करने के लिए अधिक कुशल है और परिणाम के आधार पर हम लूप के अंदर एक सरलीकृत / तेज स्थिति का उपयोग कर सकते हैं। बेहतर contains() विधि शामिल है:

public static <T> boolean contains2(final T[] array, final T v) {
    if (v == null) {
        for (final T e : array)
            if (e == null)
                return true;
    } else {
        for (final T e : array)
            if (e == v || v.equals(e))
                return true;
    }

    return false;
}

यदि आपके पास Google संग्रह लाइब्रेरी है, तो टॉम का उत्तर ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html) का उपयोग करके बहुत सरल हो सकता है।

यह वास्तव में प्रस्तावित प्रारंभ से बहुत सारे अव्यवस्था को हटा देता है

private static final Set<String> VALUES =  ImmutableSet.of("AB","BC","CD","AE");

यदि सरणी को सॉर्ट नहीं किया गया है, तो आपको सब कुछ पर फिर से भरना होगा और प्रत्येक पर बराबर कॉल करना होगा।

यदि सरणी सॉर्ट की जाती है, तो आप बाइनरी खोज कर सकते हैं, Arrays क्लास में एक है।

आम तौर पर, यदि आप बहुत सारी सदस्यता जांच करने जा रहे हैं, तो आप एक सरणी में सेट नहीं कर सकते हैं, एक सरणी में नहीं।


जांच करने के लिए चार अलग-अलग तरीके अगर एक ऐरे में एक मान होता है

1) सूची का उपयोग करना:

public static boolean useList(String[] arr, String targetValue) {
    return Arrays.asList(arr).contains(targetValue);
}

2) सेट का उपयोग करना:

public static boolean useSet(String[] arr, String targetValue) {
    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);
}

3) एक साधारण पाश का उपयोग करना:

public static boolean useLoop(String[] arr, String targetValue) {
    for (String s: arr) {
        if (s.equals(targetValue))
            return true;
    }
    return false;
}

4) Arrays.binarySearch () का उपयोग करना:

नीचे दिया गया कोड गलत है, यह पूर्णता के लिए यहां सूचीबद्ध है। बाइनरीशर्च () केवल क्रमबद्ध सरणी पर उपयोग किया जा सकता है। आप पाएंगे कि परिणाम नीचे अजीब है। सरणी सॉर्ट होने पर यह सबसे अच्छा विकल्प है।

public static boolean binarySearch(String[] arr, String targetValue) {  
            int a = Arrays.binarySearch(arr, targetValue);
            return a > 0;
        }

त्वरित उदाहरण:

String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false

जावा 8 में स्ट्रीम का उपयोग करें।

List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList
.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);





arrays