Efficiently searching arrays and collections is a foundational skill in Java development. Whether you are looking for a specific element, checking for existence, or finding the index of a match, Java provides a range of APIs and patterns — from traditional loops to modern Streams — to address these needs.
This tutorial covers common techniques for searching in both arrays and collections, including primitive arrays, object arrays, List, Set, and advanced search patterns.
H2: Searching in Arrays
Java’s Arrays utility class provides methods for searching arrays.
H3: Using Arrays.binarySearch() (Sorted Arrays)
The Arrays.binarySearch() method performs a binary search on a sorted array.
int[] numbers = {10, 20, 30, 40, 50};
int index = Arrays.binarySearch(numbers, 30);
System.out.println("Index: " + index);
Key Points:
- The array must be sorted before calling
binarySearch. - Returns the index of the found element.
- If not found, returns a negative insertion point.
int missing = Arrays.binarySearch(numbers, 25);
System.out.println(missing); // Negative value
This negative value indicates where the key would be inserted.
H3: Searching Object Arrays
For an array of objects such as String[]:
String[] names = {"Alice", "Bob", "Charlie"};
int idx = Arrays.binarySearch(names, "Bob");
The array must be sorted lexicographically for correct results.
H3: Linear Search with Loop
If the array is not sorted or you need a custom condition, use a simple loop:
String[] names = {"Alice","Bob","Charlie"};
String target = "Charlie";
int index = -1;
for (int i = 0; i < names.length; i++) {
if (names[i].equals(target)) {
index = i;
break;
}
}
System.out.println("Found at index: " + index);
This pattern works for any array type and custom matching.
H2: Searching in Collections
Java Collection types (List, Set, Map) offer flexible search operations.
H3: Searching a List
Using List.indexOf()
List<String> list = Arrays.asList("Java", "Python", "C++");
int pos = list.indexOf("Python");
System.out.println("Position: " + pos);
indexOf() returns the first matching index or -1 if not found.
Using List.contains()
boolean found = list.contains("Java");
System.out.println(found); // true
contains() tests for existence without index.
H3: Searching with Streams (Java 8+)
Streams provide expressive and flexible search patterns:
List<String> list = Arrays.asList("Java", "Python", "C++");
// Find first match
Optional<String> result = list.stream()
.filter(s -> s.startsWith("P"))
.findFirst();
result.ifPresent(System.out::println);
This allows arbitrary conditions without manual loops.
H3: Searching a Set
Sets don’t preserve order and don’t have indexes, but you can check existence:
Set<String> set = new HashSet<>(list);
boolean exists = set.contains("C++");
Use streams when you need more complex filters:
boolean match = set.stream().anyMatch(s -> s.endsWith("++"));
H3: Searching Maps
Maps store key-value pairs.
Map<String,Integer> map = new HashMap<>();
map.put("Alice", 30);
map.put("Bob", 25);
boolean hasKey = map.containsKey("Bob");
boolean hasValue = map.containsValue(30);
To find entries by condition:
map.entrySet().stream()
.filter(e -> e.getValue() > 28)
.forEach(System.out::println);
H2: Searching Primitive Arrays
Primitive arrays like int[] or double[] require slightly different handling.
H3: Using Arrays.binarySearch()
As shown earlier:
double[] values = {1.2, 3.4, 5.6};
int pos = Arrays.binarySearch(values, 3.4);
Always ensure the array is sorted.
H3: Manual Search with Loop
int[] nums = {5, 9, 1, 7};
int target = 9;
int idx = -1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) {
idx = i;
break;
}
}
Manual loops are simple and effective for small arrays.
H2: Advanced Search Patterns
H3: Custom Comparator with Binary Search
When searching sorted arrays of custom objects:
Person[] people = {...};
Arrays.sort(people, Comparator.comparing(Person::getName));
int index = Arrays.binarySearch(
people,
new Person("John", 0),
Comparator.comparing(Person::getName)
);
This allows binary search on custom fields.
H3: Finding All Matches with Streams
Using streams to collect all matches:
List<String> allMatches = list.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
This returns a new list of found elements.
H2: Performance Considerations
Arrays.binarySearch()has O(log n) complexity but requires a sorted array.- Linear search (
loop) has O(n) complexity, suitable for small or unsorted inputs. - Streams may introduce overhead for large collections but are expressive and parallelizable.
Choose technique based on performance needs and data size.
H2: Best Practices (Senior Engineering Insight)
From real enterprise experience:
- Use binarySearch for large sorted datasets to improve performance.
- Prefer Streams for expressive filtering and modern code.
- Avoid repeated searches inside loops — cache results where possible.
- When dealing with custom objects, define clear equals()/hashCode() implementations.
These practices help build efficient, maintainable search logic throughout your applications.
Summary
Searching arrays and collections in Java can be done using:
Arrays.binarySearch()for sorted arrays- Traditional loops for simple linear scanning
List.indexOf()andcontains()for collections- Streams for flexible, expressive, and complex conditions
- Custom comparators for advanced object searches
Each method has use cases and performance characteristics that you can choose based on your requirements.


