Skocz do zawartości
  • 0

Bład z List, ArrayList


KrejzolekPRO
 Udostępnij

Pytanie

Mam sobie obiekt RawBlock:

public class RawBlock {

    private Location location;
    private Material block;
    private Long time;

    public RawBlock(Location location, Material block, Long time){
        this.location = location;
        this.block = block;
        this.time = time;
        RawBlockUtil.add(this);
    }

    public Location getLocation() {
        return location;
    }

    public Material getBlock() {
        return block;
    }

    public Long getTime() {
        return time;
    }
}

I mam do niego klase RawBlockUtil:

public class RawBlockUtil {

    public static List<RawBlock> blockList = new ArrayList<>();

    public static void add(RawBlock block){
        for(RawBlock rawBlock : RawBlockUtil.blockList){
            if(block.getLocation() == rawBlock.getLocation()){
                return;
            }
        }
        RawBlockUtil.blockList.add(block);
    }

    public static void remove(RawBlock block){
        if(RawBlockUtil.blockList.contains(block)){
            RawBlockUtil.blockList.remove(block);
        }
        return;
    }

    public static Integer debug(){
        Integer amount = 0;
        for(RawBlock rawBlock : RawBlockUtil.blockList){
            rawBlock.getLocation().getBlock().setType(rawBlock.getBlock());
            RawBlockUtil.blockList.remove(rawBlock);
            amount++;
        }
        return amount;
    }
}

Przykładowe tworzenie nowego obiektu:

public void onBreak(BlockBreakEvent event) {
        if(event.getBlock().getType() == Material.IRON_ORE || event.getBlock().getType() == Material.GOLD_ORE || event.getBlock().getType() == Material.DIAMOND_ORE || event.getBlock().getType() == Material.EMERALD_ORE || event.getBlock().getType() == Material.LAPIS_ORE || event.getBlock().getType() == Material.REDSTONE_ORE || event.getBlock().getType() == Material.COAL_ORE){
            Player player = event.getPlayer();
            long time = player.hasPermission("rawcore.boosters.generator") ? 20*60*30L : 20*60*45L;
            new RawBlock(event.getBlock().getLocation(), event.getBlock().getType(), time);

Kiedy chce wykonać metodę z tym obiektem (np. debug()) to wyrzuca błąd z tą linijką:

for(RawBlock rawBlock : RawBlockUtil.blockList)

A oto błąd:

Unexpected exception while parsing console command "oregenerator zregeneruj"
org.bukkit.command.CommandException: Unhandled exception executing command 'oregenerator' in plugin rawCore vv1.1
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at org.bukkit.craftbukkit.v1_12_R1.CraftServer.dispatchCommand(CraftServer.java:648) ~[spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at org.bukkit.craftbukkit.v1_12_R1.CraftServer.dispatchServerCommand(CraftServer.java:634) [spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at net.minecraft.server.v1_12_R1.DedicatedServer.aP(DedicatedServer.java:444) [spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:407) [spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:679) [spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:577) [spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        at java.lang.Thread.run(Unknown Source) [?:?]
Caused by: java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(Unknown Source) ~[?:?]
        at java.util.ArrayList$Itr.next(Unknown Source) ~[?:?]
        at pl.krejzolekpro.rawcore.obejcts.utils.RawBlockUtil.debug(RawBlockUtil.java:30) ~[?:?]
        at pl.krejzolekpro.rawcore.commands.GeneratorCommand.onCommand(GeneratorCommand.java:15) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot-1.12.2.jar:git-Spigot-2086bb0-d0a3620]
        ... 8 more

Pierwszy raz spotkałem się z takim czymś i nie wiem jak sobie z tym poradzić.

Sllnik: Spigot 1.12.2

Java 10.

 

Edytowane przez KrejzolekPRO
Odnośnik do komentarza
Udostępnij na innych stronach

5 odpowiedzi na to pytanie

Rekomendowane odpowiedzi

  • 0

debug usuwa RawBlock z listy którą loopujesz

@KrejzolekPRO w for bierzesz liste rawblocków z utila i dalej usuwasz zawartość listy, może tam jest problem

a wgl to jest słabo zrobione weź amount zsetuj na długość listy, ustaw t e blocki na nw co i usuńzawartość całej listy

napisałem to samo i nie dostałem like, life is brutal ;(

Edytowane przez LloydPL
Odnośnik do komentarza
Udostępnij na innych stronach

  • 0
3 minuty temu, LloydPL napisał:

debug usuwa RawBlock z listy którą loopujesz

No taki ma zadania właśnie debug, chodzi ci o to?

RawBlockUtil.blockList.remove(rawBlock);

@LloydPL no tak, tylko że ja najpierw zapętlam go, a dopiero potem usuwam, więc nie operuje na znikomym obiekcie. :/

Edytowane przez KrejzolekPRO
Odnośnik do komentarza
Udostępnij na innych stronach

  • 0

Poczytaj też o hash setach no i nie robi się takich operacji w konstruktorach bo to zła praktyka, możesz zrobić statyczną metodę w tych utilsach co tworzy obiekt RawBlock i dodaje do listy, ale nie w jego konstruktorze.

Nie ma też sensu sperawdzać czy obiekt jest w kolekcji by go usunąć, bo usunięcie i tak musi to sprawdzić jeszcze raz.

A w metodzie debug możesz po prostu przeiterować po całej liście a potem za pętlą ją wyczyścić metodą .clear, nie musisz też wtedy liczyć amount tylko zwrócić rozmiar listy przed wyczyszczeniem.

 

Bo nie można edytować listy po której się iteruje (no to dodatkowe zabezpieczenie javy przed nieprawidłowym używaniem wątków itd, są kolekcje co to wspierają większym kosztem pamięciowym/wydajnościpwym)

+ można to robić w szczególnych przypadkach, np klasa Iterator ma metod removę oraz można iterować po indexach

Edytowane przez GotoFinal
Odnośnik do komentarza
Udostępnij na innych stronach

  • 0
12 minut temu, GotoFinal napisał:

Poczytaj też o hash setach no i nie robi się takich operacji w konstruktorach bo to zła praktyka, możesz zrobić statyczną metodę w tych utilsach co tworzy obiekt RawBlock i dodaje do listy, ale nie w jego konstruktorze.

Nie ma też sensu sperawdzać czy obiekt jest w kolekcji by go usunąć, bo usunięcie i tak musi to sprawdzić jeszcze raz.

A w metodzie debug możesz po prostu przeiterować po całej liście a potem za pętlą ją wyczyścić metodą .clear, nie musisz też wtedy liczyć amount tylko zwrócić rozmiar listy przed wyczyszczeniem.

 

Bo nie można edytować listy po której się iteruje (no to dodatkowe zabezpieczenie javy przed nieprawidłowym używaniem wątków itd, są kolekcje co to wspierają większym kosztem pamięciowym/wydajnościpwym)

+ można to robić w szczególnych przypadkach, np klasa Iterator ma metod removę oraz można iterować po indexach

Dzięki bardzo, wszystko działa! :)

Odnośnik do komentarza
Udostępnij na innych stronach

Nieaktywny
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
 Udostępnij

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...