--- a/net/minecraft/server/players/StoredUserList.java
+++ b/net/minecraft/server/players/StoredUserList.java
@@ -28,7 +_,7 @@
     private static final Logger LOGGER = LogUtils.getLogger();
     private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
     private final File file;
-    private final Map<String, V> map = Maps.newHashMap();
+    private final Map<String, V> map = Maps.newConcurrentMap(); // Paper - Use ConcurrentHashMap in StoredUserList
     protected final NotificationService notificationService;
 
     public StoredUserList(File file, NotificationService notificationService) {
@@ -60,8 +_,11 @@
 
     @Nullable
     public V get(K obj) {
-        this.removeExpired();
-        return this.map.get(this.getKeyForUser(obj));
+        // Paper start - Use ConcurrentHashMap in StoredUserList
+        return this.map.computeIfPresent(this.getKeyForUser(obj), (k, v) -> {
+            return v.hasExpired() ? null : v;
+        });
+        // Paper end - Use ConcurrentHashMap in StoredUserList
     }
 
     public boolean remove(K key) {
@@ -98,7 +_,7 @@
     }
 
     public boolean isEmpty() {
-        return this.map.size() < 1;
+        return this.map.isEmpty(); // Paper - Use ConcurrentHashMap in StoredUserList
     }
 
     protected String getKeyForUser(K obj) {
@@ -106,21 +_,12 @@
     }
 
     protected boolean contains(K entry) {
+        this.removeExpired(); // CraftBukkit - SPIGOT-7589: Consistently remove expired entries to mirror .get(...)
         return this.map.containsKey(this.getKeyForUser(entry));
     }
 
     private void removeExpired() {
-        List<K> list = Lists.newArrayList();
-
-        for (V storedUserEntry : this.map.values()) {
-            if (storedUserEntry.hasExpired()) {
-                list.add(storedUserEntry.getUser());
-            }
-        }
-
-        for (K object : list) {
-            this.map.remove(this.getKeyForUser(object));
-        }
+        this.map.values().removeIf(StoredUserEntry::hasExpired); // Paper - Use ConcurrentHashMap in StoredUserList
     }
 
     protected abstract StoredUserEntry<K> createEntry(JsonObject entryData);
@@ -130,6 +_,7 @@
     }
 
     public void save() throws IOException {
+        this.removeExpired(); // Paper - remove expired values before saving
         JsonArray jsonArray = new JsonArray();
         this.map.values().stream().map(storedEntry -> Util.make(new JsonObject(), storedEntry::serialize)).forEach(jsonArray::add);
 
@@ -154,7 +_,14 @@
                         this.map.put(this.getKeyForUser(storedUserEntry.getUser()), (V)storedUserEntry);
                     }
                 }
+            // Spigot start
+            } catch (com.google.gson.JsonParseException | NullPointerException ex) {
+                File backup = new File(this.file + ".backup");
+                LOGGER.warn("Unable to read file {}, backing it up to {} and creating new copy.", this.file, backup, ex);
+                this.file.renameTo(backup);
+                this.file.delete();
             }
+            // Spigot end
         }
     }
 }
