diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java index 714ca8bd3a3..f8ee6a44f8a 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; @@ -217,7 +216,6 @@ public enum NameSource { } static final ZipArchiveEntry[] EMPTY_ARRAY = {}; - static LinkedList EMPTY_LINKED_LIST = new LinkedList<>(); public static final int PLATFORM_UNIX = 3; public static final int PLATFORM_FAT = 0; diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java index 351cdc96fe7..3a5f309b183 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java @@ -30,6 +30,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -368,9 +369,14 @@ public static void closeQuietly(final ZipFile zipFile) { private final List entries = new LinkedList<>(); /** - * Maps String to list of ZipArchiveEntrys, name -> actual entries. + * Maps a string to the first entry by that name. */ - private final Map> nameMap = new HashMap<>(HASH_SIZE); + private final Map nameMap = new HashMap<>(HASH_SIZE); + + /** + * If multiple entries have the same name, maps the name to entries by that name. + */ + private Map> duplicateNameMap; /** * The encoding to use for file names and the file comment. @@ -749,8 +755,22 @@ private void fillNameMap() { // entries are filled in populateFromCentralDirectory and // never modified final String name = ze.getName(); - final LinkedList entriesOfThatName = nameMap.computeIfAbsent(name, k -> new LinkedList<>()); - entriesOfThatName.addLast(ze); + final ZipArchiveEntry firstEntry = nameMap.putIfAbsent(name, ze); + + if (firstEntry != null) { + if (duplicateNameMap == null) { + duplicateNameMap = new HashMap<>(); + } + + final List entriesOfThatName = duplicateNameMap.computeIfAbsent(name, k -> { + // Create a list when there are two entries with the same name + final ArrayList list = new ArrayList<>(2); + list.add(firstEntry); + return list; + }); + + entriesOfThatName.add(ze); + } }); } @@ -820,7 +840,13 @@ public Enumeration getEntries() { * @since 1.6 */ public Iterable getEntries(final String name) { - return nameMap.getOrDefault(name, ZipArchiveEntry.EMPTY_LINKED_LIST); + final List entriesOfThatName = duplicateNameMap == null ? null : duplicateNameMap.get(name); + if (entriesOfThatName == null) { + final ZipArchiveEntry entry = nameMap.get(name); + return entry != null ? Collections.singletonList(entry) : Collections.emptyList(); + } else { + return Collections.unmodifiableList(entriesOfThatName); + } } /** @@ -847,8 +873,16 @@ public Enumeration getEntriesInPhysicalOrder() { * @since 1.6 */ public Iterable getEntriesInPhysicalOrder(final String name) { - final LinkedList linkedList = nameMap.getOrDefault(name, ZipArchiveEntry.EMPTY_LINKED_LIST); - return Arrays.asList(sortByOffset(linkedList.toArray(ZipArchiveEntry.EMPTY_ARRAY))); + if (duplicateNameMap != null) { + final List list = duplicateNameMap.get(name); + if (list != null) { + final ZipArchiveEntry[] entriesOfThatName = list.toArray(ZipArchiveEntry.EMPTY_ARRAY); + return Arrays.asList(sortByOffset(entriesOfThatName)); + } + } + + final ZipArchiveEntry entry = nameMap.get(name); + return entry != null ? Collections.singletonList(entry) : Collections.emptyList(); } /** @@ -862,8 +896,7 @@ public Iterable getEntriesInPhysicalOrder(final String name) { * @return the ZipArchiveEntry corresponding to the given name - or {@code null} if not present. */ public ZipArchiveEntry getEntry(final String name) { - final LinkedList entries = nameMap.get(name); - return entries != null ? entries.getFirst() : null; + return nameMap.get(name); } /**