There is a method that checks for the presence of an element in an array:

private boolean existA(String a) { for (String s : massStringA) { if (a.equals(s)) { return true; } } return false; } 

Is this method optimal, or is it a “bicycle”, and is there a more optimal solution to this problem?

  • Is the array sorted? Can I sort it out? - Mikhail Vaysman
  • The array is not sorted, the order of its elements does not matter - Jorik
  • Use what you wrote, this is a normal solution for an array of <= 15 elements. - Artem Konovalov

4 answers 4

If you do not touch on the issue of sorting, the shorter form will be

 return Arrays.asList(massStringA).contains(s); 

(note, Arrays.asList() does not create a copy of the array, but uses the original, so it does not double the memory consumption).

    If the array can be sorted, then you can speed up the search engine.

     String[] massStringA = ...; // массив будет изменен! Arrays.sort(massStringA); if(Arrays.binarySearch(massStringA, a) >= 0) { // строка найдена }; 

    If the array cannot be modified and Java 8 is used, then Stream can be applied.

     if(Arrays.stream(massStringA).anyMatch(s -> s.equals(a))) { // строка найдена } 

      A better solution is to copy the String[] to HashSet<String> , then use the contains method of the HashSet .

      Made an artificial example. Perhaps the actual data results will differ.

       private static final int STRINGS_COUNT = 100 * 1000, TESTS_COUNT = 100 * 1000; private static final HashSet<String> hashSet = new HashSet<>(); private static final String[] massStringA = new String[STRINGS_COUNT]; public static void main(String[] args) { for (int i = 0; i < STRINGS_COUNT; i++) { massStringA[i] = createString(i); } long startTime = System.currentTimeMillis(); hashSet.addAll(Arrays.asList(massStringA)); System.out.println("Copy time: " + (System.currentTimeMillis() - startTime) + "ms"); Random rand = new Random(); String[] testStrings = new String[TESTS_COUNT]; for (int i = 0; i < TESTS_COUNT; i++) { int randValue = rand.nextInt(STRINGS_COUNT * 10); testStrings[i] = createString(randValue); } startTime = System.currentTimeMillis(); int matches = 0; for (int i = 0; i < TESTS_COUNT; i++) { if (existA(testStrings[i])) { matches++; } } System.out.println("Array search time: " + (System.currentTimeMillis() - startTime) + "ms, matches: " + matches); startTime = System.currentTimeMillis(); matches = 0; for (int i = 0; i < TESTS_COUNT; i++) { if (Arrays.asList(massStringA).contains(testStrings[i])) { matches++; } } System.out.println("Arrays.asList search time: " + (System.currentTimeMillis() - startTime) + "ms, matches: " + matches); startTime = System.currentTimeMillis(); matches = 0; for (int i = 0; i < TESTS_COUNT; i++) { if (hashSet.contains(testStrings[i])) { matches++; } } System.out.println("HashSet search time: " + (System.currentTimeMillis() - startTime) + "ms, matches: " + matches); } private static String createString(int number) { int value = number; StringBuilder sb = new StringBuilder(); while (value > 0) { sb.append((char)(value % 80 + 47)); value /= 80; } return sb.toString(); } private static boolean existA(String a) { for (String s : massStringA) { if (a.equals(s)) { return true; } } return false; } 

      For 100 thousand tests with 100 thousand lines, the results are as follows:

       Copy time: 16ms Array search time: 69762ms, matches: 9858 Arrays.asList search time: 73248ms, matches: 9858 HashSet search time: 14ms, matches: 9858 

      For a million tests with 10 thousand lines:

       Copy time: 3ms Array search time: 17775ms, matches: 99845 Arrays.asList search time: 17537ms, matches: 99845 HashSet search time: 26ms, matches: 99845 
      • Why not use Set instead of Map ? - temq
      • @temq stupid habit of using HashMap where HashSet or TreeMap more suitable. Changed to HashSet , thanks. - Regent
      • It all depends strongly on the use of the method. If the author rarely uses it, then there is no point in copying into the hashset, we will only achieve an increase in overhead data from memory and a deterioration of data locality. If the array is relatively not large, then a simple iteration and comparison is perhaps the best solution. - Artem Konovalov
      • Thank you very much for such hard work, and for the statistics. The example uses a small array of strings <15 elements - Jorik
      • @ArtemKonovalov if there are few elements in the array (less than 15 elements, as it turned out above), then you can even search for O(n^4) - nothing will change: it will be about a couple of ms. The question in this case (and there was an emphasis on optimality) was devoid of any meaning. - Regent

      You can use the contains method

      public boolean contains (CharSequence s)

      Here is an example of checking for the presence of the string "abc" in the string "abcdgd;aoihvfsl" :

       String string = "abcdgd;aoihvfsl"; if (string.contains(String.valueOf("abc")) 

      In this case, will return true .

      • The question is about the array, not about the string. - Mikhail Vaysman