Согласно вашему комментарию, вы ищете оптимизацию скорости. В Интернете много публикаций, сравнивающих Stream и Collection и даже больше.
Я рекомендую вам в качестве примера взглянуть на этот вопрос, который сравнивает быстродействие потоков и старого для каждого цикла:
Java 8: производительность потоков против коллекций .
Поскольку использование Stream создает много промежуточных объектов и вызывает промежуточные методы, кажется нормальным быть медленнее, чем базовый для каждого цикла.
Однако вы можете использовать поток, чтобы иметь более читаемый / меньший код.
Чтобы ответить на вопрос, я думаю, ваш код уже очень хорош, учитывая быстродействие. Все, что я вижу, это то, что вы должны инициализировать adminAreaID, потому что вы точно знаете его размер:
Set<String> adminAreaID = new HashSet<>(adminAreaSet.size(), 1.);
Установив размер и коэффициент загрузки, вы гарантируете, что не будете тратить время на выращивание вашего устройства.
Согласно https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html:
Коэффициент загрузки является мерой того, насколько полна хеш-таблица
получить до того, как его емкость будет автоматически увеличена.
Вы должны установить его на 1. потому что вы не увеличите размер adminAreaSet. Более того, если вы укажете значение 0,75 (значение по умолчанию), ваш набор увеличится один раз, когда цикл достигнет 75% своей емкости, что бесполезно.
Если у вас нет проблем с памятью, вы должны сделать то же самое с помощью FilterSet:
Set<Student> filteredSet = new HashSet<>(unfilteredSet.size(), 1.);
Фактически, когда вы фильтруете нефильтрованный набор, вы не достигнете максимальной емкости, но это гарантирует, что фильтр не будет расти во время его заполнения.