Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192

Рефакторинг в сторону лямбда-выражения

23.08.2017, 12:50. Показов 1077. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Недавно начал изучать новые потоковые методы и лямбда выражения в Java.
Столкнулся с проблемой, что не могу сделать правильный рефакторинг старого кода.
на данный момент он выглядит так:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
    public void addFrustumMap(Map<Float, List<IEntity>> frustumMap) {
        if ((frustumMap != null) && (!frustumMap.isEmpty())) {
            frustumMap.keySet().stream()
                .filter(key -> this.frustumEntities.containsKey(key))
                .peek(key -> {
                    List<IEntity> batch = frustumMap.get(key);
                    batch.addAll(this.frustumEntities.get(key));
                    this.frustumEntities.put(key, batch);
                });
            frustumMap.keySet().stream()
            .filter(key -> !this.frustumEntities.containsKey(key))
            .peek(key -> {
                this.frustumEntities.put(key, frustumMap.get(key));
            });
        }
    }
Но я понимаю, что это убого. Как переписать данный код, чтобы можно было все выполнить в одной цепочке?
frustumEntities - это поле класса, который использует описанный метод, с типом Map<Float, List<IEntity>>.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.08.2017, 12:50
Ответы с готовыми решениями:

Лямбда выражения
Добрый день, помогите, пожалуйста с лямбдой. Нужно переписать вот это: public static boolean CheckingString(String string) { ...

Лямбда выражения
В одной теме https://www.cyberforum.ru/java-j2se/thread1794469 пользователь xoraxax показал код private static final int a =...

Конструкторы и лямбда выражения
Добрый день. Появился вопрос при изучении лямбда выражений и ссылок на конструкторы. Пример из книги: interface MyFunc{ MyClass func...

13
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
23.08.2017, 15:21
Цитата Сообщение от homelleon Посмотреть сообщение
.peek
не используй пик так, лучше вообще не используй.
Цитата Сообщение от homelleon Посмотреть сообщение
List<IEntity> batch = frustumMap.get(key);
* * * * * * * * * * batch.addAll(this.frustumEntities.get(ke y));
* * * * * * * * * * this.frustumEntities.put(key, batch);
вот это вот все выглядит совершенно отвратительно, не читается, не понятно, что делает
пользуйся filter->map>collect, пиши функции
0
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
23.08.2017, 17:19  [ТС]
Оказывается можно просто сделать так:
this.frustumEntities.putAll(frustumMap);
XD
А вот тут посложнее:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
    public void updateWithFrustum(Frustum frustum) {
        this.frustumEntities.clear();
        this.getAll().forEach(entity -> {
            float distance = frustum.distanceSphereInFrustum(entity.getPosition(), entity.getSphereRadius());
            if (distance >= 0 && distance < EngineSettings.RENDERING_VIEW_DISTANCE) {
                List<IEntity> batch = this.frustumEntities.containsKey(distance) ?
                        frustumEntities.get(distance) : new ArrayList<IEntity>();
                batch.add(entity);
                this.frustumEntities.put(distance, batch);
            }
        });
    }
Можно как-то упростить в сторону лямбда-выражений?
0
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
24.08.2017, 00:28
Можно Машку за ляжку, что должно делать?
1
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
24.08.2017, 16:22  [ТС]
Цитата Сообщение от xoraxax Посмотреть сообщение
Можно Машку за ляжку, что должно делать?
Какую Машку?
Данный метод добавляет все сущности из List<IEntity> (getAll()) в Map<Float,List<IEntity>> frustumEntities - входящие в пирамиду видимости.
Для того, чтобы они были добавлены, нужно, чтобы выполнялось условие:
distance >= 0 && distance < EngineSettings.RENDERING_VIEW_DISTANCE
При этом float distance = frustum.distanceSphereInFrustum(entity.g etPosition(), entity.getSphereRadius());
В мапу добавляются distance как ключ и как объект - List<IEntity>, при этом List<IEntity> нужно сформировать из всех IEntity entity, которые прошли проверку.
При этом с каждой итерации List<IEntity> из getAll() может быть такое, что в Map<Float,List<IEntity>>frustumEntities уже есть ключ, равный distance данной итерации. Поэтому, если там есть ключ, то извлекается объект как List<IEntity>batch и ему добавляется IEntity entity из данной итерации, а если нет такого ключа, то создается новый List<IEntity>batch и ему также присваивается IEntity entity из данной итерации. А потом batch добавляется в Map<Float,List<IEntity>>frustumEntities
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.08.2017, 17:04
Такую историю ищешь? https://docs.oracle.com/javase... .Function-
0
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
24.08.2017, 17:21  [ТС]
Цитата Сообщение от vcrop Посмотреть сообщение
Такую историю ищешь?
нет, это не то. Проблема не в том, как создать Map<T,R>, а в том, как записать правильно фильтрацию в данном случае. Если можно сделать преобразование map(entity -> (entity, float distance = ...))
То можно было бы просто написать
getAll().stream()
.map(entity->(entity, float distance = ...))
.filter((entity, distance) -> ...>distance<...)
Но функция возвращает только одно значение.
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.08.2017, 17:35
зачем тебе distance таскать?
Function<IEntity, Float> distance = e -> frustum.distanceSphereInFrustum(e.getPos ition(), e.getSphereRadius());

соответственно predicate
Predicate<IEntity> predicate = e -> distance.apply(e) >= 0 && distance.apply(e) < ...;

И в конце мапа
frustumEntities = getAll().stream().filter(predicate::test ).collect(Collectors.groupingBy(distance ::apply));
1
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
24.08.2017, 17:50  [ТС]
Цитата Сообщение от vcrop Посмотреть сообщение
зачем тебе distance таскать?
Function<IEntity, Float> distance = e -> frustum.distanceSphereInFrustum(e.getPos ition(), e.getSphereRadius());
соответственно predicate
Predicate<IEntity> predicate = e -> distance.apply(e) >= 0 && distance.apply(e) < ...;
И в конце мапа
frustumEntities = getAll().stream().filter(predicate::test ).collect(Collectors.groupingBy(distance ::apply));
Но тогда мы вычисляем distance 4 раза.
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.08.2017, 18:01
Если жизненно важно - напиши какой-нить Pair.
getAll().stream().map(e -> new Pair<IEntity, Float>(e, distance.apply(e))) ....
и дальше уже со стримом <Pair> - filter - collect.
0
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
24.08.2017, 18:43  [ТС]
Цитата Сообщение от vcrop Посмотреть сообщение
getAll().stream().map(e -> new Pair<IEntity, Float>(e, distance.apply(e))) ....
Наверное это подойдет...
Значит мы получаем на выходи эту пару, Pair<IEntity, Float>(e, distance.apply(e)), у этой пары должны быть методы getFirst и getSecond, потом надо сделать filter(pair -> predicate.test(pair.getFirst)), после надо создать мапу с ключами pair.getFirst и объектом Collectors.toList(pair.getSecond)... я тут не совсем понимаю, что дальше нужно делать.
Как создавать лист из этого?
0
502 / 348 / 134
Регистрация: 14.06.2016
Сообщений: 669
24.08.2017, 20:39
типа такого чего-то
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void updateWithFrustum(Frustum frustum) {
 
        class G {
 
            final IEntity entity;
            final float distance;
 
            G(IEntity entity) {
                this.entity = entity;
                distance = frustum.distanceSphereInFrustum(entity.getPosition(), entity.getSphereRadius());
            }
 
            boolean valid() { return distance >= 0 && distance < EngineSettings.RENDERING_VIEW_DISTANCE; }
 
            IEntity getEntity() { return entity; }
 
            float getDistance() { return distance; }
 
        }
 
        frustumEntities = this.getAll().stream().map(G::new).filter(G::valid).collect(groupingBy(G::getDistance, mapping(G::getEntity, toList())));
 
    }
Добавлено через 15 минут
Ты показал только один метод. Посмотри, может в IEntity можно повесить поле distance, тогда отпадают лишние внутренние классы.
1
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
29.08.2017, 18:56  [ТС]
Цитата Сообщение от vcrop Посмотреть сообщение
Ты показал только один метод. Посмотри, может в IEntity можно повесить поле distance, тогда отпадают лишние внутренние классы.
Спасибо! У меня получилось так записать, как написал ты, и я вроде стал лучше понимать, как это работает.
Просто я нашел баг и не мог проверить правильность данного кода.

Я не могу сделать поле distance для IEntity, потому что это будет нагружать лишней информацией, тем более что distance используется только в данном коде, в данной мапе.
И почему-то запись G::valid не работает - приходится писать (group -> group.valid).

Но все-таки мне кажется, что создавать внутренний класс в методе не очень продуктивно. Наверно есть другой способ, как элегантно передать distance.

Добавлено через 3 часа 49 минут
Еще у меня есть такой код:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
for (int i = 0; i < chunkManager.getSize(); i++) {
            if (checkVisibility(frustum, chunkManager.getChunkPosition(i), CHUNK_RADIUS)) {
                if (chunkManager.getChunk(i).getIsAcitve()) {
                    FaceCullingData chunkFCData = isNeedChunkCulling(chunkManager, i);
                    for (int x = 0; x <= EngineSettings.VOXEL_CHUNK_SIZE; x++) {
                        for (int y = 0; y <= EngineSettings.VOXEL_CHUNK_SIZE; y++) {
                            for (int z = 0; z <= EngineSettings.VOXEL_CHUNK_SIZE; z++) {
                                if (checkVisibility(frustum, chunkManager.getBlockPosition(i, new Vector3i(x, y, z)),
                                        BLOCK_RADIUS)) {
                                    FaceCullingData blockFCData = isNeedBlockCulling(chunkManager.getChunk(i), x, y, z);
                                    if (!isAllFaceCulled(blockFCData)) {
                                        if (chunkManager.getChunk(i).getBlock(x, y, z).getIsActive()) {
                                            prepareInstance(chunkManager.getBlockPosition(i, new Vector3i(x, y, z)));
                                            for (int j = 0; j < 6; j++) {
                                                if (!blockFCData.getFace(j)) {
                                                    GL12.glDrawRangeElements(GL11.GL_TRIANGLES, 0, 6, 6,
                                                            GL11.GL_UNSIGNED_INT, 24 * j);
                                                }
                                            }
                                        }
                                    }
                                    blockFCData = null;
                                }
                            }
                        }
                    }
                    chunkFCData = null;
                }
            }
        }
        unbindTexturedModel();
        shader.stop();
    }
Он выглядит ужасно без Stream API. Я знаю, что можно использовать
IntStream.range(0, chunkManager.getSize())
.filter(i -> checkVisibility(frustum, chunkManager.getChunkPosition(i), CHUNK_RADIUS))
.filter(i -> chunkManager.getChunk(i).getIsAcitve())
. -А что надо писать тут, чтобы можно было подцепить еще один цикл for для x, потом также для y и z? Мне нужно передавать туда все i, x, y и z, т.е. нужно сохранять куда-то эти переменные.
Я сделал внутренний класс
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Index {
            private int i;
            private int x;
            private int y;
            private int z;
            
            public Index(int i) {
                this.i = i;
            }
            
            public int getI() {
                return i;
            }
            
            public Index setX(int x) {
                this.x = x;
                return this;
            }
            
            public int getX() {
                return x;
            }
            
            public Index setY(int y) {
                this.y = y;
                return this;
            }
            
            public int getY() {
                return y;
            }
            
            public Index setZ(int z) {
                this.z = z;
                return this;
            }
            
            public int getZ() {
                return z;
            }
        }
И знаю, что можно сделать MapToObj(i -> Index.new(i)), потом мне опять надо же вызвать IntStream, чтобы прогнать по x, y и z и вызвать команды new Index(i).setX(x), new Index(i).setX(x).setY(y), new Index(i).setX(x).setY(y).setZ(z). Хотя тогда придется создавать гораздо больше объектов класса Index, чем нужно.

Добавлено через 2 часа 20 минут
Что-то мне подсказывает, что можно еще упростить:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        class Index {
            private int i;
            private int x;
            private int y;
            private int z;
            private FaceCullingData fcd;
            
            public Index(int i) {
                this.i = i;
            }
            
            public int getI() {
                return i;
            }
            
            public Index setX(int x) {
                this.x = x;
                return this;
            }
            
            public int getX() {
                return x;
            }
            
            public Index setY(int y) {
                this.y = y;
                return this;
            }
            
            public int getY() {
                return y;
            }
            
            public Index setZ(int z) {
                this.z = z;
                return this;
            }
            
            public int getZ() {
                return z;
            }
            
            public Index setFCD(FaceCullingData fcd) {
                this.fcd = fcd;
                return this;
            }
            
            public FaceCullingData getFCD() {
                return this.fcd;
            }
        }
        
        IntStream.range(0, chunkManager.getSize())
            .filter(i -> checkVisibility(frustum, chunkManager.getChunkPosition(i), CHUNK_RADIUS))
            .filter(i -> chunkManager.getChunk(i).getIsAcitve())
            .mapToObj(Index::new)
            .flatMap(index -> IntStream.range(0, EngineSettings.VOXEL_CHUNK_SIZE+1)
                        .mapToObj(x -> new Index(index.getI())
                                .setX(x))
                    )
            .flatMap(index -> IntStream.range(0, EngineSettings.VOXEL_CHUNK_SIZE+1)
                        .mapToObj(y -> new Index(index.getI())
                                .setX(index.getX()).setY(y))
                        )
            .flatMap(index -> IntStream.range(0, EngineSettings.VOXEL_CHUNK_SIZE+1)
                    .mapToObj(z -> new Index(index.getI())
                            .setX(index.getX()).setY(index.getY()).setZ(z))
                    )
            .peek(index -> index.setFCD(isNeedBlockCulling(chunkManager.getChunk(
                        index.getI()), index.getX(), index.getY(), index.getZ())))
            .filter(index ->
                !isAllFaceCulled(index.getFCD())
                    )
            .filter(index -> chunkManager.getChunk(
                    index.getI()).getBlock(index.getX(), index.getY(), index.getZ())
                        .getIsActive())
            .forEach(index -> { 
                        prepareInstance(chunkManager.getBlockPosition(
                                index.getI(), new Vector3i(
                                        index.getX(), index.getY(), index.getZ()))
                                );
                        IntStream.range(0, 6)
                            .filter(face -> !index.getFCD().getFace(face))
                            .forEachOrdered(face -> GL12.glDrawRangeElements(GL11.GL_TRIANGLES, 0, 6, 6,
                                                                GL11.GL_UNSIGNED_INT, 24 * face));
                    }
                );
0
4 / 4 / 3
Регистрация: 15.12.2012
Сообщений: 192
10.09.2017, 09:26  [ТС]
А как такое упростить?
Java
1
2
3
4
5
6
7
8
9
10
entities.keySet()
            .forEach(model -> {
                prepareLowTexturedModel(model);
                entities.get(model)
                    .forEach(entity -> {
                        prepareInstance(entity);
                        GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
                    });
                    unbindTexturedModel();
            });
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.09.2017, 09:26
Помогаю со студенческими работами здесь

Лямбда-выражения в Java
Подскажите пожалуйста, как переписать следующий класс с использованием лямбда-выражений? Хотя бы некоторые методы. import java.io.*; ...

Лямбда-выражения и ссылки на методы
Господа, может кто-нибудь подсказать доступную инфу по лямбда-выражениям и ссылкам на методы. В большинстве статей в инете, все слишком...

Лямбда выражения, проверка правила согласно логике в объекте
Здравствуйте, есть задача вида: &quot;Написать метод: public void showStudent(Student s, Show rule). Выводящий на экран имена студентов из...

Лямбда-выражения. Как описать лямбда-процедуру и передать в нее файловую переменную?
Погуглив не смогла найти ответов на свои вопросы. Есть следующая процедура, которая находит положительные числа в одном файле и...

Лямбда выражения
Как сделать таккую выборку? Есть три коллекции: Добавить в третью коллекцию те элементы, где элемент первой коллекции равен элементу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru