Почему Arrays.Stream () не изменяет int [] внутри метода в Java

Я пытаюсь обработать некоторые побитовые операции с числами int []. Для каждой операции я создаю отдельный статический метод непосредственно внутри класса Main и передаю массив чисел, а также битовую позицию, которую я хочу изменить. На самом деле ничего интересного.

Мой вопрос, вероятно, очень глупый, но поскольку Java ВСЕГДА передает по значению, почему мои методы не меняют мой источник, когда я использую Arrays.stream (numbers []) ... но только когда я использую for-loop.

В обоих случаях я передаю ссылку на массив, почему он не работает, помогите, пожалуйста, это сводит меня с ума :(

public class Main {
public static void main(String[] args) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    int n = Integer.parseInt(reader.readLine());
    int [] numbers = new int[n];
    for (int i =0; i < n; i++) {
        numbers[i] = Integer.parseInt(reader.readLine());
    }

    String line = reader.readLine();
    while (!"party over".equalsIgnoreCase(line)) {
        String operation = line.split("\\s+")[0];
        int position = Integer.parseInt(line.split("\\s+")[1]);
        switch (operation) {
            case  "-1":
                flipTheBitAtPosition (numbers, position);
                break;
            case "0" :
                turnBitAtPositionToZero (numbers, position);
                break;
            case "1":
                turnBitAtPositionToOne(numbers, position);
                break;
        }


        line = reader.readLine();
    }

    Arrays.stream(numbers).forEach(x-> System.out.println(x));
}

private static void turnBitAtPositionToOne(int[] numbers, int position) {
    int mask = 1 <<position;
   //this does not modifty the numbers array
    Arrays.stream(numbers).map(x-> x|mask);

    //this does modify the numbers array Why ?!
    for (int i =0; i < numbers.length; i++) {
        numbers[i] |= mask;
    }

}

private static void turnBitAtPositionToZero(int[] numbers, int position) {
    int mask =  ~(1 <<position);
    //this does not modifty the numbers array
    Arrays.stream(numbers).map(x->x & mask);
}

private static void flipTheBitAtPosition(int[] numbers, int position) {
    int mask = 1 <<position;
    //this does not modifty the numbers array
   Arrays.stream(numbers).map(x->x ^ mask);

}

}

Как вы думаете, почему это должно происходить? Почему у вас сложилось впечатление, что Arrays.stream что-то делает с входным массивом?

Sotirios Delimanolis 19.09.2018 17:27

Вам следует создать небольшой пример с меньшей логикой, чтобы тестировать материал и задавать здесь вопросы. Сделайте пример с одним методом и без особых ветвлений.

HopefullyHelpful 19.09.2018 17:28

Также ищите промежуточные и конечные операции.

Sotirios Delimanolis 19.09.2018 17:31
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
296
2

Ответы 2

Arrays.stream(numbers).map(x-> x +2);

Этот код создает поток целых чисел, а затем отображает его в измененный поток целых чисел. Ни в коем случае он не присваивает значения массиву и не возвращает массив через терминальную операцию. Это можно рассматривать как поток незавершенной работы, поскольку вы не вызвали никаких операций терминала, таких как toArray или forEach.

Итак, используя Stream, у вас есть два варианта. Или:

  1. вернуть новый массив, а затем назначить его (или скопировать в) исходной переменной.
  2. или используйте forEach для присвоения каждого индекса ... это похоже на потоковую версию цикла for.

Если вы выберете вариант №1, вы будете использовать toArray(int[]::new) или аналогичный.

Если вы выберете вариант №2, я бы рекомендовал начать с IntStream.range(numbers.length), поскольку это упростит назначение по заданным индексам.

«map ()» не должен изменять исходный поток (который в любом случае неизменен, AFAIK). Он просто возвращает новый поток (не беспокойтесь об эффективности базового хранилища, потому что это всего лишь поток, но все же). Если хотите, можете просто записать новый результат в новую переменную. Но в вашем случае цикл for кажется достаточно хорошим.

Другие вопросы по теме