2

I have a doubt about the performance difference between these two things, get an object directly from a hashmap with the key vs get it from an Optional from an ArrayList. I will use these to save big amounts of data.

Note: the example below is only to show what I mean; I don't use static except in utils or specific things, I say this to prevent comments about static.

public class Main {

    private static final List<User> users = Arrays.asList(new User(UUID.randomUUID()), new User(UUID.randomUUID()), new User(UUID.randomUUID()));

    public static Optional<User> getUserByUUID(final UUID uuid){
        return users.stream().filter(user -> user.getUuid().equals(uuid)).findFirst();
    }

    @RequiredArgsConstructor
    @Getter@Setter
    private static class User{
        private final UUID uuid;
        private int points;
        private int gems;
    }

}

vs

public class Main {

    private static final Map<UUID, User> users = new HashMap<UUID, User>(){{
        put(UUID.randomUUID(), new User());
        put(UUID.randomUUID(), new User());
    }};
            

    public static User getUserByUUID(final UUID uuid){
        if(users.containsKey(uuid))
            return users.get(uuid);
        return null;
    }

    @RequiredArgsConstructor
    @Getter@Setter
    private static class User{
        private int points;
        private int gems;
    }

}

My point is, if one is better than the another one in terms of performance, is it insignificant?

R3bck
  • 43
  • 5
  • You can simplify your code in the map version to `return users.get(uuid);`. Checking for `containsKey` and then using `get` **doubles** the cost, where just using `get` suffices. – Mark Rotteveel Apr 11 '21 at 08:49

1 Answers1

8

Map#get will always be more performant than creating a Stream from a List and looking for a specific entry.

Map#get will give you a time complexity of O(1) basically

List#stream instead will give you a time complexity of O(n) plus extra space complexity: creation of a Stream and creation of an Optional


That said, if you have big amounts of data loaded in memory, this might lead to performance problems / OutOfMemoryErrors

It would be interesting to dig further in the problem and see if there isn't another way to handle this specific problem without loading big amounts of data directly in memory of the JVM

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
  • I'm saving and loding data into SQLite or MySQL, so i have no way to save memory in another place since it's a plugin, and my question was because i won't have just one HashMap or just one Arrays, I need a few for what I have in mind – R3bck Apr 10 '21 at 23:17
  • @R3bck ok if your process is backed by a database, that's already great. Don't hesitate to benchmark your process too. – Yassin Hajaj Apr 10 '21 at 23:26
  • Yes i'm using hikari for a pool , and i already knew about the O(1) and O(n) but my point was if the answer if the same for big amount of data and multiple arrays or maps, i use SQLLite or MySQL just for load data and save data when the plugin ends, also i save data async while plugin is running – R3bck Apr 10 '21 at 23:30
  • 1
    Yes the answer remains the same anyway @R3bck, the second part is just an extra – Yassin Hajaj Apr 10 '21 at 23:31
  • 1
    @R3bck If you're using a database, then _let the database do its job_ and make a SQL query instead of keeping your own in-memory copy. – chrylis -cautiouslyoptimistic- Apr 11 '21 at 00:10
  • @chrylis -cautiouslyoptimistic- that'd be soooo bad for what i'm doing – R3bck Apr 11 '21 at 00:28