Skip to content

Commit 83ccabf

Browse files
Improve performance
1 parent 4fd536e commit 83ccabf

File tree

1 file changed

+117
-54
lines changed

1 file changed

+117
-54
lines changed

src/main/java/me/flame/menus/menu/Page.java

Lines changed: 117 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package me.flame.menus.menu;
22

3+
import com.google.common.base.Preconditions;
34
import com.google.common.collect.ImmutableSet;
5+
46
import lombok.Setter;
7+
58
import me.flame.menus.items.MenuItem;
69
import me.flame.menus.menu.iterator.PageIterator;
710

@@ -20,21 +23,21 @@ public final class Page implements Iterable<MenuItem> {
2023
@NotNull
2124
private final PaginatedMenu holder;
2225

23-
@NotNull
24-
private final Map<Integer, MenuItem> itemMap;
25-
2626
@NotNull
2727
private final PageIterator iterator = new PageIterator(IterationDirection.HORIZONTAL, this);
28-
29-
private final int size, rows;
3028

31-
private @Setter boolean dynamicSizing;
29+
@Setter
30+
private boolean dynamicSizing;
31+
32+
int size, rows;
33+
34+
MenuItem[] itemMap;
3235

3336
private Page(final @NotNull PaginatedMenu holder) {
3437
this.holder = holder;
3538
this.size = holder.size;
3639
this.rows = holder.rows;
37-
this.itemMap = new HashMap<>(size);
40+
this.itemMap = new MenuItem[size];
3841
this.dynamicSizing = holder.isDynamicSizing();
3942
}
4043

@@ -51,26 +54,29 @@ private Page(final @NotNull PaginatedMenu holder) {
5154
*/
5255
public boolean addItem(@NotNull final ItemStack... items) {
5356
final List<ItemStack> notAddedItems = new ArrayList<>();
54-
final Set<Integer> occupiedSlots = itemMap.keySet();
57+
5558

5659
int slot = 0;
5760
for (final ItemStack guiItem : items) {
5861
if (slot >= size) {
62+
if (rows == 6) break; // save some performance
5963
notAddedItems.add(guiItem);
6064
continue;
6165
}
6266

63-
while (occupiedSlots.contains(slot)) {
64-
slot++;
65-
}
67+
slot = getSlot(itemMap, slot);
6668

67-
itemMap.put(slot, MenuItem.of(guiItem));
69+
try {
70+
itemMap[slot] = MenuItem.of(guiItem);
71+
} catch (IndexOutOfBoundsException e) { // slot will only get bigger when too high so exit
72+
break;
73+
}
6874
slot++;
6975
}
7076

71-
if (dynamicSizing && !notAddedItems.isEmpty() && (this.rows < 6 && holder.getType() == MenuType.CHEST)) {
72-
holder.recreateInventory();
73-
holder.update();
77+
if (this.dynamicSizing && !notAddedItems.isEmpty() && (this.rows < 6 && this.holder.getType() == MenuType.CHEST)) {
78+
this.holder.recreateInventory();
79+
this.holder.update();
7480
return this.addItem(notAddedItems.toArray(new ItemStack[0]));
7581
}
7682
return true;
@@ -83,20 +89,22 @@ public boolean addItem(@NotNull final ItemStack... items) {
8389
*/
8490
public boolean addItem(@NotNull final MenuItem... items) {
8591
final List<MenuItem> notAddedItems = new ArrayList<>();
86-
final Set<Integer> occupiedSlots = itemMap.keySet();
8792

8893
int slot = 0;
8994
for (final MenuItem guiItem : items) {
9095
if (slot >= size) {
96+
if (rows == 6) break; // save some performance
9197
notAddedItems.add(guiItem);
9298
continue;
9399
}
94100

95-
while (occupiedSlots.contains(slot)) {
96-
slot++;
97-
}
101+
slot = getSlot(itemMap, slot);
98102

99-
itemMap.put(slot, guiItem);
103+
try {
104+
itemMap[slot] = guiItem;
105+
} catch (IndexOutOfBoundsException e) { // slot will only get bigger when too high so exit
106+
break;
107+
}
100108
slot++;
101109
}
102110

@@ -108,13 +116,33 @@ public boolean addItem(@NotNull final MenuItem... items) {
108116
return true;
109117
}
110118

119+
private static boolean isSlotGreater(Collection<MenuItem> notAddedItems, int slot, int size, MenuItem guiItem) {
120+
if (slot < size) return false;
121+
notAddedItems.add(guiItem);
122+
return true;
123+
}
124+
125+
126+
private static boolean isSlotGreater(Collection<ItemStack> notAddedItems, int slot, int size, ItemStack guiItem) {
127+
if (slot < size) return false;
128+
notAddedItems.add(guiItem);
129+
return true;
130+
}
131+
132+
private static int getSlot(MenuItem[] occupiedSlots, int slot) {
133+
while (occupiedSlots[slot] != null) {
134+
slot++;
135+
}
136+
return slot;
137+
}
138+
111139
/**
112140
* Set the item at the specified slot in the page.
113141
* @param slot the slot to set
114142
* @param item the item to set
115143
*/
116144
public void setItem(int slot, MenuItem item) {
117-
itemMap.put(slot, item);
145+
this.itemMap[slot] = item;
118146
}
119147

120148
/**
@@ -123,7 +151,7 @@ public void setItem(int slot, MenuItem item) {
123151
* @param item the item to set
124152
*/
125153
public void setItem(int slot, ItemStack item) {
126-
itemMap.put(slot, MenuItem.of(item));
154+
this.itemMap[slot] = MenuItem.of(item);
127155
}
128156

129157
/**
@@ -133,7 +161,7 @@ public void setItem(int slot, ItemStack item) {
133161
*/
134162
public void setItem(Slot slot, MenuItem item) {
135163
if (!slot.isSlot()) return;
136-
itemMap.put(slot.slot, item);
164+
this.itemMap[slot.slot] = item;
137165
}
138166

139167
/**
@@ -143,7 +171,7 @@ public void setItem(Slot slot, MenuItem item) {
143171
*/
144172
public void setItem(Slot slot, ItemStack item) {
145173
if (!slot.isSlot()) return;
146-
itemMap.put(slot.slot, MenuItem.of(item));
174+
this.itemMap[slot.slot] = MenuItem.of(item);
147175
}
148176

149177
/**
@@ -153,15 +181,15 @@ public void setItem(Slot slot, ItemStack item) {
153181
public void removeItem(MenuItem... items) {
154182
Set<MenuItem> slots = ImmutableSet.copyOf(items);
155183

156-
int size = itemMap.size();
184+
int size = itemMap.length;
157185
Inventory inventory = holder.getInventory();
158186
for (int i = 0; i < size; i++) {
159-
MenuItem item = itemMap.get(i);
187+
MenuItem item = itemMap[i];
160188
if (item == null) continue;
161189

162190
ItemStack itemStack = item.getItemStack();
163191
if (slots.contains(item)) {
164-
itemMap.remove(i);
192+
remove(i);
165193
inventory.remove(itemStack);
166194
}
167195
}
@@ -174,15 +202,15 @@ public void removeItem(MenuItem... items) {
174202
public void removeItem(ItemStack... items) {
175203
Set<ItemStack> slots = ImmutableSet.copyOf(items);
176204

177-
int size = itemMap.size();
205+
int size = itemMap.length;
178206
Inventory inventory = holder.getInventory();
179207
for (int i = 0; i < size; i++) {
180-
MenuItem item = itemMap.get(i);
208+
MenuItem item = itemMap[i];
181209
if (item == null) continue;
182210

183211
ItemStack itemStack = item.getItemStack();
184212
if (slots.contains(itemStack)) {
185-
itemMap.remove(i);
213+
remove(i);
186214
inventory.remove(itemStack);
187215
}
188216
}
@@ -193,10 +221,10 @@ public void removeItem(ItemStack... items) {
193221
* @param itemDescription the predicate to check
194222
*/
195223
public void removeItem(Predicate<MenuItem> itemDescription) {
196-
int size = itemMap.size();
224+
int size = itemMap.length;
197225
for (int i = 0; i < size; i++) {
198-
MenuItem item = itemMap.get(i);
199-
if (item != null && itemDescription.test(item)) itemMap.remove(i);
226+
MenuItem item = itemMap[i];
227+
if (item != null && itemDescription.test(item)) remove(i);
200228
}
201229
}
202230

@@ -207,7 +235,7 @@ public void removeItem(Predicate<MenuItem> itemDescription) {
207235
* @return the removed item
208236
*/
209237
public MenuItem removeItem(Slot slot) {
210-
return itemMap.remove(slot.slot);
238+
return remove(slot.slot);
211239
}
212240

213241
/**
@@ -217,7 +245,7 @@ public MenuItem removeItem(Slot slot) {
217245
* @return the removed item
218246
*/
219247
public MenuItem removeItem(int slot) {
220-
return itemMap.remove(slot);
248+
return remove(slot);
221249
}
222250

223251
/**
@@ -226,8 +254,13 @@ public MenuItem removeItem(int slot) {
226254
* @param slot the slot to check
227255
* @return the item or null
228256
*/
229-
public MenuItem getItem(Slot slot) {
230-
return itemMap.get(slot.slot);
257+
public @Nullable MenuItem getItem(Slot slot) {
258+
if (!slot.isSlot()) return null;
259+
try {
260+
return itemMap[slot.slot];
261+
} catch (IndexOutOfBoundsException e) {
262+
return null;
263+
}
231264
}
232265

233266
/**
@@ -236,8 +269,12 @@ public MenuItem getItem(Slot slot) {
236269
* @param slot the slot to check
237270
* @return the item or null
238271
*/
239-
public MenuItem getItem(int slot) {
240-
return itemMap.get(slot);
272+
public @Nullable MenuItem getItem(int slot) {
273+
try {
274+
return itemMap[slot];
275+
} catch (IndexOutOfBoundsException e) {
276+
return null;
277+
}
241278
}
242279

243280
/**
@@ -246,10 +283,10 @@ public MenuItem getItem(int slot) {
246283
* @return the item or null
247284
*/
248285
public @Nullable MenuItem getItem(Predicate<MenuItem> itemDescription) {
249-
int size = itemMap.size();
250-
for (int i = 0; i < size; i++) {
251-
MenuItem item = itemMap.get(i);
252-
if (item != null && itemDescription.test(item)) return item;
286+
for (MenuItem item : itemMap) {
287+
if (item != null && itemDescription.test(item)) {
288+
return item;
289+
}
253290
}
254291
return null;
255292
}
@@ -261,7 +298,12 @@ public MenuItem getItem(int slot) {
261298
* @return the item
262299
*/
263300
public Optional<MenuItem> get(Slot slot) {
264-
return Optional.ofNullable(itemMap.get(slot.slot));
301+
if (!slot.isSlot()) return Optional.empty();
302+
try {
303+
return Optional.ofNullable(itemMap[slot.slot]);
304+
} catch (IndexOutOfBoundsException e) {
305+
return Optional.empty();
306+
}
265307
}
266308

267309
/**
@@ -271,7 +313,11 @@ public Optional<MenuItem> get(Slot slot) {
271313
* @return the item
272314
*/
273315
public Optional<MenuItem> get(int slot) {
274-
return Optional.ofNullable(itemMap.get(slot));
316+
try {
317+
return Optional.ofNullable(itemMap[slot]);
318+
} catch (IndexOutOfBoundsException e) {
319+
return Optional.empty();
320+
}
275321
}
276322

277323
/**
@@ -280,9 +326,8 @@ public Optional<MenuItem> get(int slot) {
280326
* @return the item
281327
*/
282328
public Optional<MenuItem> get(Predicate<MenuItem> itemDescription) {
283-
int size = itemMap.size();
284-
for (int i = 0; i < size; i++) {
285-
MenuItem item = itemMap.get(i);
329+
int size = itemMap.length;
330+
for (MenuItem item : itemMap) {
286331
if (item != null && itemDescription.test(item)) return Optional.of(item);
287332
}
288333
return Optional.empty();
@@ -320,23 +365,23 @@ public PageIterator iterator(int startingRow, int startingCol, IterationDirectio
320365
* Clear the entire page.
321366
*/
322367
public void clear() {
323-
itemMap.clear();
368+
Arrays.fill(itemMap, null);
324369
}
325370

326371
/**
327372
* Get a stream of every value in the map.
328373
* @return the stream
329374
*/
330375
public Stream<MenuItem> stream() {
331-
return itemMap.values().stream();
376+
return Arrays.stream(itemMap).parallel();
332377
}
333378

334379
/**
335380
* Get a <strong>PARALLEL</strong> stream of every value in the map.
336381
* @return the parallel stream
337382
*/
338383
public Stream<MenuItem> parallelStream() {
339-
return itemMap.values().parallelStream();
384+
return Arrays.stream(itemMap).parallel();
340385
}
341386

342387
/**
@@ -369,16 +414,34 @@ public int rows() {
369414
* @return true if there is an item
370415
*/
371416
public boolean hasItem(int slot) {
372-
return itemMap.get(slot) != null;
417+
return itemMap[slot] != null;
373418
}
374419

375420
/**
376421
* Check if the page has an item at the specified slot.
377422
* @param slot the slot
378423
* @return true if there is an item
379424
*/
380-
public boolean hasItem(Slot slot) {
425+
public boolean hasItem(@NotNull Slot slot) {
381426
if (!slot.isSlot()) return false;
382-
return itemMap.get(slot.slot) != null;
427+
return itemMap[slot.slot] != null;
428+
}
429+
430+
private MenuItem remove(int index) {
431+
int length = this.itemMap.length;
432+
Preconditions.checkElementIndex(index, length);
433+
434+
MenuItem item = this.itemMap[index];
435+
this.itemMap[index] = null;
436+
return item;
437+
}
438+
439+
public void setContents(MenuItem... items) {
440+
this.itemMap = items;
441+
this.holder.update();
442+
}
443+
444+
public List<MenuItem> getItems() {
445+
return Arrays.asList(itemMap);
383446
}
384447
}

0 commit comments

Comments
 (0)