Vc poderia usar uma Busca Binária.
A classe Collections tem o método binarySearch para te ajudar nisso, vc só precisa fazer o ObjetoX implementar a interface Comparable.
Vc só precisa assegurar que a lista esteja organizada antes de invocar o método binarySearch.
Olha como ficaria:
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class ObjetoX implements Comparable<ObjetoX> {
String propriedadeY;
ObjetoX(int propriedadeY) {
this.propriedadeY = "Objeto " + propriedadeY;
}
@Override
public String toString() {
return propriedadeY;
}
@Override
public int compareTo(ObjetoX o) {
return this.propriedadeY.compareTo(o.propriedadeY);
}
}
public class App {
public static void main(String... args) {
int max = 10_000_000;
List<ObjetoX> list = IntStream.range(0, max).mapToObj(ObjetoX::new).collect(Collectors.toList());
int index = Collections.binarySearch(list, new ObjetoX(max / 2));
System.out.println(list.get(index));
}
}
Para vc ter uma ideia do poder deste algoritmo, para encontrar o ObjetoX 500000 ele leva apenas coisa de 23 passos!
Um ponto que pode ser inconveniente pra vc é que tem que criar um objeto que vai representar o valor que vc está procurando, por isso eu criei aquele new ObjetoX(max / 2).
Se preferir implementar o algoritmo “na mão”, seria algo assim:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class ObjetoX {
String propriedadeY;
ObjetoX(int propriedadeY) {
this.propriedadeY = "Objeto " + propriedadeY;
}
@Override
public String toString() {
return propriedadeY;
}
}
public class Main {
public static void main(String... args) {
int max = 10_000_000;
List<ObjetoX> list = IntStream.range(0, max).mapToObj(ObjetoX::new).collect(Collectors.toList());
String goal = "Objeto " + max / 2;
ObjetoX result = binarySearch(list, goal);
System.out.println(result);
}
protected static ObjetoX binarySearch(List<ObjetoX> list, String goal) {
ObjetoX[] array = list.toArray(new ObjetoX[0]);
Arrays.sort(array, (a, b) -> a.propriedadeY.compareTo(b.propriedadeY));
int low = 0;
int high = array.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
String propriedadeY = array[mid].propriedadeY;
if (propriedadeY.equals(goal))
return array[mid];
else if (propriedadeY.compareTo(goal) > 0)
high = mid - 1;
else
low = mid + 1;
}
return null;
}
}
Eu não sei se há uma opção melhor, mas vale a pena considerar a sugestão.