Solved Getting the largest int in an ArrayList<Integer>

Discussion in 'Spigot Plugin Development' started by PCPSells, Jul 26, 2018.

  1. Hey SpigotMC!
    I'm currently trying to get the highest int from a config file.

    Code:
    Code (Java):
    ArrayList<Integer> l = new ArrayList<Integer>();
            for (String s : cfg.getStringList("Backpacks." + type + "." + id + ".Items")) {
                l.add(Integer.parseInt(s));
            } Integer maxValue = Collections.max(l) + 1;
    Everytime the code is ran, I get a NoSuchElementException error.

    Error -
    Code (Java):
    [21:14:09] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'crates' in plugin ACCrates v1.0
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[server.jar:git-Spigot-3fb9445-6e3cec8]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[server.jar:git-Spigot-3fb9445-6e3cec8]
        at org.bukkit.craftbukkit.v1_11_R1.CraftServer.dispatchCommand(CraftServer.java:650) ~[server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.PlayerConnection.handleCommand(PlayerConnection.java:1354) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:1189) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.PacketPlayInChat.a(PacketPlayInChat.java:45) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.PacketPlayInChat.a(PacketPlayInChat.java:1) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.PlayerConnectionUtils$1.run(SourceFile:13) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_171]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_171]
        at net.minecraft.server.v1_11_R1.SystemUtils.a(SourceFile:46) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:747) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:399) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:678) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:576) [server.jar:git-Spigot-3fb9445-6e3cec8]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
    Caused by: java.util.NoSuchElementException
        at java.util.ArrayList$Itr.next(ArrayList.java:862) ~[?:1.8.0_171]
        at java.util.Collections.max(Collections.java:669) ~[?:1.8.0_171]
        at backpacks.BackpackInteraction.addItemToPlayersBackpack(BackpackInteraction.java:207) ~[?:?]
        at me.PCPSells.Main.onCommand(Main.java:369) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[server.jar:git-Spigot-3fb9445-6e3cec8]
        ... 15 more
    and line 207 is of course:
    Code (Java):
    Integer maxValue = Collections.max(l) + 1;
    Any help would be appreciated! Thank you in advance! :D
     
  2. Java 8 Solution:
    Code (Text):
    myList.stream()
    .sorted(Comparator.reverseOrder()) //Sorts integers from highest to lowest (actually sorts anything from highest to lowest that implements Comparable)
    .limit(1); //Collects 1 element from list. If you wanted top 5 then you'd put 5
    //if you wanted top 5 like I mentioned, you'd append limit with .collect(Collectors.toList()
    I've tested this with 1,000,000 elements and it only took 8 seconds IIRC.
    Another Solution:
    Code (Text):
    int highest = 0;
    for(Integer int : integerList) {
    highest = Math.max(int, highest);
    }
     
    #2 Fluddershy, Jul 26, 2018
    Last edited: Jul 26, 2018
    • Informative Informative x 1
  3. I tried the 1st method and get this error -
    [​IMG]

    I tried the second method:
    Code (Java):
    int highest = 0;
            for(Integer i : l) {
                highest = Math.max(i, highest) + 1;
                p.sendMessage("In Loop - " + highest);
                }
    and I never receive that "In Loop - " message at all.
     
  4. Code (Java):
    int biggest = list.stream().reduce(Integer.MIN_VALUE, Integer::max);
    else reduce it only to return an optional if none is found.
     
  5. Code:
    Code (Java):
    ArrayList<Integer> l = new ArrayList<Integer>();
            for (String s : cfg.getStringList("Backpacks." + type + "." + id + ".Items")) {
                l.add(Integer.parseInt(s));
                p.sendMessage("Added - " + s);
            } int highest = l.stream().reduce(Integer.MIN_VALUE, Integer::max);
                 p.sendMessage("Final - " + highest);
    Output:
    [​IMG]

    List:
    [​IMG] (1 & 2)

    I also never receive the "Added -" message so I'm assuming that's why?
    Not sure why it's not looping if that's the case.
     
  6. Show your entire configuration. I'm not sure if you're purposely requesting a list, because it seems to be a configuration section instead.
     
  7. A whole bunch of errors here nobody is addressing.

    The exception is due to the list having nothing in it, because the config entries dont exist.

    You should use int, not Integer (look up the difference).

    You dont need to use Collections.max, just count each value while loading and see if it is higher than the previous value - half as much work.
     
  8. It is actually. How would I format then?

    Entire config:
    Code (YAML):
    Backpacks:
      Shards
    :
        '0'
    :
          Title
    : '&3Shards &bBackpack &8(&3#0&8)'
          Size
    : 54
          Items
    :
            '1'
    :
              Item
    : PRISMARINE_SHARD:0
              Amount
    : 5
              Name
    : §3§m---§b§m------§7§l(§6King§7§l)§3§m---§b§m------§f Shard
              Lore
    :
             - §e/warp crate
     
     
  9. Get the configuration section "Items" (you'll need to navigate yourself into the section since it's nested) which will in return give you a set of keys, being the '1', '2', etc. Parse them as integers, if they are, and follow something as:

    Code (Java):
    int highest = fileConfiguration.getConfigurationSection("Items").stream()
    .     .filter(this::isInteger)
          .reduce(minimum, Integer::max);


    private boolean isInteger(String input) {
         try {
              return Integer.parseInt(input) > 0;
         } catch(NumberFormatException exception) {
              return false;
         }
    }
    As I said before, if you're looking to catch the case where there is no biggest integer, just have it return an OptionalInt.
     
    • Informative Informative x 1
  10. [​IMG]
    [​IMG]
    [​IMG]
     
  11. Figured it out :) Thank you everyone!
     
  12. Regarding the minimum;
    a result of what happens when you copy psuedo code. This was meant as your own input.

    Regarding the stream;
    Again, psuedo code, you need to stream the keys of the section, not the section itself

    As for the static,
    I assume the method you copy-pasted my psuedo code under is static, which likely isn't suppose to and is resulting in static abuse. Either properly use static or continue what you're doing and make the isInteger function static.
     
  13. Instead of a filter, you should use flatMapToInt and have the isInt method return an IntStream (either an empty one if it fails, or one with a single element if it parses)