[Git][java-team/libfastutil-java][upstream] New upstream version 8.5.16+dfsg
Pierre Gruet (@pgt)
gitlab at salsa.debian.org
Tue Aug 19 08:39:44 BST 2025
Pierre Gruet pushed to branch upstream at Debian Java Maintainers / libfastutil-java
Commits:
c2513627 by Pierre Gruet at 2025-08-19T08:03:49+02:00
New upstream version 8.5.16+dfsg
- - - - -
16 changed files:
- .gitignore
- CHANGES
- README.md
- build.properties
- drv/ArrayFIFOQueue.drv
- drv/Arrays.drv
- drv/Map.drv
- drv/OpenHashMap.drv
- gencsource.sh
- src/it/unimi/dsi/fastutil/HashCommon.java
- src/it/unimi/dsi/fastutil/Stack.java
- src/it/unimi/dsi/fastutil/io/FastByteArrayOutputStream.java
- src/it/unimi/dsi/fastutil/io/InspectableFileCachedInputStream.java
- src/overview.html
- test/it/unimi/dsi/fastutil/objects/Object2IntOpenHashMapTest.java
- + test/it/unimi/dsi/fastutil/objects/Object2ObjectMapTest.java
Changes:
=====================================
.gitignore
=====================================
@@ -6,13 +6,19 @@ src/it/unimi/dsi/fastutil/*.c
src/it/unimi/dsi/fastutil/*.h
pom.xml
pom.xml.asc
+pom-core.xml
+pom-core.xml.asc
dist
-docs
+docs/*
+docs-core/*
+src-core/*
+workspace/*
+reports/*
build
bin
fastutil-*.jar
fastutil*.txt
-pom-*.xml
.classpath
.project
.ant-targets-build.xml
+.idea
=====================================
CHANGES
=====================================
@@ -1,3 +1,17 @@
+8.5.16
+
+- Removed InspectableFileCachedInputStream.finalize().
+
+- New utility methods and usability improvements for array-based FIFO
+ queues and FastByteArrayOutputStream. Thanks to Andrej Fink for
+ implementing these features.
+
+- Following a report by Jesse Rosenstock, some inconsistency in the usage
+ of Double.doubleToLongBits()/Double.doubleToRawLongBits() and
+ Float.floatToIntBits()/Float.floatToRawIntBits() has been fixed. The
+ changes will avoid confusion between different types of NaNs, but
+ should not have any impact on users.
+
8.5.15
- Fixed a very long-standing subtle bug that was causing unnecessary
=====================================
README.md
=====================================
@@ -1,26 +1,39 @@
-# Welcome to fastutil
+# Welcome to `fastutil`!
-[fastutil](http://fastutil.di.unimi.it/) extends the Java Collections
-Framework by providing type-specific maps, sets, lists, and queues with a
-small memory footprint and fast access and insertion; it provides also big
-(64-bit) arrays, sets, and lists, sorting algorithms, fast, practical I/O
-classes for binary and text files, and facilities for memory mapping large
-files.
+[](https://search.maven.org/search?q=g:%22it.unimi.dsi%22%20AND%20a:%22fastutil%22)
+[](https://javadoc.io/doc/it.unimi.dsi/fastutil)
-Since version 8.5.5, fastutil is split into two jars for convenience:
+## Introduction
-- `fastutil-core.jar` contains data structures based on integers, longs,
- doubles, and objects;
+`fastutil` extends the [Java™ Collections
+Framework](http://download.oracle.com/javase/1.5.0/docs/guide/collections/)
+by providing type-specific maps, sets, lists and queues with a small
+memory footprint and fast access and insertion; it also provides big
+(64-bit) arrays, sets and lists, and fast, practical I/O classes for
+binary and text files. It is free software distributed under the [Apache
+License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
-- `fastutil.jar` is the classic distribution, containing all classes.
+The classes implement their standard counterpart interface (e.g., `Map`
+for maps) and can be plugged into existing code. Moreover, they provide
+additional features (such as bidirectional iterators) that are not
+available in the standard classes.
-Note that core classes are duplicated in the standard jar, so if you are
+Besides objects and primitive types, `fastutil` classes provide support
+for _references_, that is, objects that are compared using the equality
+operator rather than the `equals()` method.
+
+The sources are generated using a C preprocessor, starting from a set of
+driver files. You can peek at the `javadoc`-generated documentation. In
+particular, the overview explains the design choices used in `fastutil`.
+
+## Core jar
+
+If the standard `fastutil` jar is too large, there is a _core_ jar
+containing only data structures specific for integers, longs and doubles.
+Note that those classes are duplicated in the standard jar, so if you are
depending on both (for example, because of transitive dependencies) you
should exclude the core jar.
-Previous split versions would provide different classes in different jars,
-but managing sensibly dependencies turned out to be impossible.
-
You can also create a small, customized fastutil jar (which you can put in
your repo, local maven repo, etc.) using the `find-deps.sh` shell script.
It has mild prerequisites, as only the `jdeps` tool is required (bundled
@@ -33,7 +46,7 @@ First, you have to `make sources` to get the actual Java sources.
After that, `ant jar` will generate a single jar file; `ant javadoc` will
generate the API documentation; `ant junit` will run the unit tests.
-If you want to obtain the three jars above, you have to run the script
+If you want to obtain the two jars above, you have to run the script
`split.sh`, and then `ant osgi-rest`.
The Java sources are generated using a C preprocessor. The `gencsource.sh`
@@ -42,5 +55,33 @@ preprocessor-defined symbols and some conditional compilation, and produces a
(fake) C source, which includes the driver code and some definitions that
customize the environment.
-* seba (<mailto:sebastiano.vigna at unimi.it>)
-* https://groups.google.com/g/fastutil
+## Speed
+
+`fastutil` provides in many cases the fastest implementations available.
+You can find many other implementations of primitive collections (e.g.,
+[HPPC](http://labs.carrotsearch.com/hppc.html),
+[Koloboke](https://github.com/leventov/Koloboke), etc.). Sometimes authors
+are a little bit quick in defining their implementations the “fastest
+available“: the truth is, you have to take decisions in any
+implementation. These decisions make your implementation faster or slower
+in different scenarios. I suggest to _always_ test speed within your own
+application, rather than relying on general benchmarks, and ask the
+authors for suggestions about how to use the libraries in an optimal way.
+In particular, when testing hash-based data structures you should always
+set explicitly the load factor, as speed is strongly dependent on the
+length of collision chains.
+
+## Big Data Structures
+
+With `fastutil` 6, a new set of classes makes it possible to handle very
+large collections: in particular, collections whose size exceeds
+2<sup>31</sup>. Big arrays are arrays-of-arrays handled by a wealth of
+static methods that act on them as if they were monodimensional arrays
+with 64-bit indices, and big lists provide 64-bit list access. The size of
+a hash big set is limited only by the amount of core memory.
+
+## Discussion
+
+There is a [discussion group](http://groups.google.com/group/fastutil)
+about `fastutil`. You can join or [send a
+message](mailto:fastutil at googlegroups.com).
=====================================
build.properties
=====================================
@@ -3,7 +3,7 @@ javadoc.base=/usr/share/javadoc
build.sysclasspath=ignore
-version=8.5.15
+version=8.5.16
dist=dist
src=src
=====================================
drv/ArrayFIFOQueue.drv
=====================================
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2024 Sebastiano Vigna
+ * Copyright (C) 2010-2025 Sebastiano Vigna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
package PACKAGE;
#if KEY_CLASS_Object
@@ -223,4 +222,37 @@ public class ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC,
final KEY_GENERIC_TYPE[] array = this.array = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[length = HashCommon.nextPowerOfTwo(end + 1)];
for(int i = 0; i < end; i++) array[i] = KEY_GENERIC_CAST s.READ_KEY();
}
-}
+
+ /** Returns the physical capacity of the queue (internal array). */
+ public int capacity() {
+ return length;
+ }
+
+ /** @see java.util.Collection#toArray() */
+ public KEY_GENERIC_TYPE[] toArray() {
+ final KEY_GENERIC_TYPE[] tmp = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[size()];
+ if (start <= end){
+ System.arraycopy(array, start, tmp, 0, end - start);// [..ssssseeee...] -> [ssssseeee]
+ } else {
+ System.arraycopy(array, start, tmp, 0, length - start); //[eeee...{sssss}] -> [sssss]
+ System.arraycopy(array, 0, tmp, length - start, end);//[{eeee}...sssss] -> [ssssseeee]
+ }
+ return tmp;
+ }
+
+ @Override
+ public String toString() {
+ int size = size();
+ StringBuilder sb = new StringBuilder(size * 9 + 3).append('[');
+ for (int i = start; size-- > 0; ){
+ sb.append(array[i++]).append(", ");
+ if (i == length) i = 0;// wrap index
+ }
+
+ if (sb.length() > 2){// cut last ', '
+ sb.setLength(sb.length() - 2);
+ }
+
+ return sb.append(']').toString();
+ }
+}
\ No newline at end of file
=====================================
drv/Arrays.drv
=====================================
@@ -1853,12 +1853,12 @@ public final class ARRAYS {
/** This method fixes negative numbers so that the combination exponent/significand is lexicographically sorted. */
#if KEY_CLASS_Double
private static final long fixDouble(final double d) {
- final long l = Double.doubleToLongBits(d);
+ final long l = Double.doubleToRawLongBits(d);
return l >= 0 ? l : l ^ 0x7FFFFFFFFFFFFFFFL;
}
#elif KEY_CLASS_Float
private static final int fixFloat(final float f) {
- final int i = Float.floatToIntBits(f);
+ final int i = Float.floatToRoawIntBits(f);
return i >= 0 ? i : i ^ 0x7FFFFFFF;
}
#endif
=====================================
drv/Map.drv
=====================================
@@ -823,6 +823,45 @@ public interface MAP KEY_VALUE_GENERIC extends FUNCTION KEY_VALUE_GENERIC, Map<K
#endif
+ /** Returns an unmodifiable, type-specific map with the specified entries.
+ * See {@link java.util.Map#ofEntries(Map.Entry[])} */
+#if !KEYS_PRIMITIVE || !VALUES_PRIMITIVE
+ @SafeVarargs
+ @SuppressWarnings({"varargs", "unchecked"})
+#else
+ @SuppressWarnings("varargs")
+#endif
+ static KEY_VALUE_GENERIC MAP KEY_VALUE_GENERIC ofEntries(MAP.Entry KEY_VALUE_GENERIC ... entries) {
+ if (entries.length == 0) return MAPS.EMPTY_MAP;
+ if (entries.length == 1) return MAPS.singleton(entries[0].ENTRY_GET_KEY(), entries[0].ENTRY_GET_VALUE());
+
+ if (entries.length <= 8) {
+ KEY_GENERIC_TYPE[] keys = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[entries.length];
+ VALUE_GENERIC_TYPE[] vals = VALUE_GENERIC_ARRAY_CAST new VALUE_TYPE[entries.length];
+
+ for (int i = 0; i < entries.length; ++i) {
+ MAP.Entry KEY_VALUE_GENERIC entry = entries[i];
+ keys[i] = entry.ENTRY_GET_KEY();
+ // Prevent duplicate keys
+ for (int j = 0; j < i; ++j) if (KEY_EQUALS(keys[j], keys[i])) throw new IllegalArgumentException("duplicate key: " + keys[i]);
+ vals[i] = entry.ENTRY_GET_VALUE();
+ }
+ return MAPS.unmodifiable(new ARRAY_MAP KEY_VALUE_GENERIC_DIAMOND(keys, vals, entries.length));
+ } else {
+ MAP KEY_VALUE_GENERIC newMap = new OPEN_HASH_MAP KEY_VALUE_GENERIC_DIAMOND(entries.length, 0.75f);
+ for (MAP.Entry KEY_VALUE_GENERIC entry : entries) {
+ if (!VALUE_IS_NULL(newMap.put(entry.ENTRY_GET_KEY(), entry.ENTRY_GET_VALUE()))) throw new IllegalArgumentException("duplicate key: " + entry.ENTRY_GET_KEY());
+ }
+ return MAPS.unmodifiable(newMap);
+ }
+ }
+
+ /** Returns an unmodifiable, type-specific entry.
+ * See {@link java.util.Map#entry(Object, Object)} */
+ static KEY_VALUE_GENERIC Entry KEY_VALUE_GENERIC entry(KEY_GENERIC_TYPE key, VALUE_GENERIC_TYPE value) {
+ return new ABSTRACT_MAP.BasicEntry KEY_VALUE_GENERIC_DIAMOND(key, value);
+ }
+
/** A type-specific {@link java.util.Map.Entry}; provides some additional methods
* that use polymorphism to avoid (un)boxing.
*
=====================================
drv/OpenHashMap.drv
=====================================
@@ -1253,6 +1253,25 @@ public class OPEN_HASH_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP KEY_VALUE_GENE
return value[pos] = newVal;
}
+#if VALUES_PRIMITIVE && ! VALUE_CLASS_Boolean
+ /** {@inheritDoc} */
+ @Override
+ public VALUE_GENERIC_TYPE MERGE_VALUE(final KEY_GENERIC_TYPE k, final VALUE_GENERIC_TYPE v, METHOD_ARG_VALUE_BINARY_OPERATOR remappingFunction) {
+ java.util.Objects.requireNonNull(remappingFunction);
+ REQUIRE_VALUE_NON_NULL(v)
+
+ final int pos = find(k);
+ if (pos < 0) {
+ insert(-pos - 1, k, v);
+ return v;
+ }
+
+ final VALUE_GENERIC_TYPE newValue = remappingFunction.VALUE_OPERATOR_APPLY(value[pos], v);
+
+ return value[pos] = newValue;
+ }
+#endif
+
/** {@inheritDoc} */
@Override
public VALUE_GENERIC_TYPE merge(final KEY_GENERIC_TYPE k, final VALUE_GENERIC_TYPE v, final java.util.function.BiFunction<? super VALUE_GENERIC_CLASS, ? super VALUE_GENERIC_CLASS, ? extends VALUE_GENERIC_CLASS> remappingFunction) {
=====================================
gencsource.sh
=====================================
@@ -738,13 +738,13 @@ $(if [[ "${CLASS[$k]}" != "" && "${CLASS[$v]}" != "" ]]; then\
"#define KEY_EQUALS_NOT_NULL(x,y) ( (x).equals(y) )\n"\
"#define KEY_IS_NULL(x) ( (x) == null )\n"\
"#elif KEY_CLASS_Float\n"\
-"#define KEY_EQUALS(x,y) ( Float.floatToIntBits(x) == Float.floatToIntBits(y) )\n"\
-"#define KEY_EQUALS_NOT_NULL(x,y) ( Float.floatToIntBits(x) == Float.floatToIntBits(y) )\n"\
-"#define KEY_IS_NULL(x) ( Float.floatToIntBits(x) == 0 )\n"\
+"#define KEY_EQUALS(x,y) ( Float.floatToRawIntBits(x) == Float.floatToRawIntBits(y) )\n"\
+"#define KEY_EQUALS_NOT_NULL(x,y) ( Float.floatToRawIntBits(x) == Float.floatToRawIntBits(y) )\n"\
+"#define KEY_IS_NULL(x) ( Float.floatToRawIntBits(x) == 0 )\n"\
"#elif KEY_CLASS_Double\n"\
-"#define KEY_EQUALS(x,y) ( Double.doubleToLongBits(x) == Double.doubleToLongBits(y) )\n"\
-"#define KEY_EQUALS_NOT_NULL(x,y) ( Double.doubleToLongBits(x) == Double.doubleToLongBits(y) )\n"\
-"#define KEY_IS_NULL(x) ( Double.doubleToLongBits(x) == 0 )\n"\
+"#define KEY_EQUALS(x,y) ( Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y) )\n"\
+"#define KEY_EQUALS_NOT_NULL(x,y) ( Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y) )\n"\
+"#define KEY_IS_NULL(x) ( Double.doubleToRawLongBits(x) == 0 )\n"\
"#else\n"\
"#define KEY_EQUALS(x,y) ( (x) == (y) )\n"\
"#define KEY_EQUALS_NOT_NULL(x,y) ( (x) == (y) )\n"\
@@ -770,13 +770,13 @@ $(if [[ "${CLASS[$k]}" != "" && "${CLASS[$v]}" != "" ]]; then\
"#define VALUE_EQUALS_NOT_NULL(x,y) ( (x).equals(y) )\n"\
"#define VALUE_IS_NULL(x) ( (x) == null )\n"\
"#elif VALUE_CLASS_Float\n"\
-"#define VALUE_EQUALS(x,y) ( Float.floatToIntBits(x) == Float.floatToIntBits(y) )\n"\
-"#define VALUE_EQUALS_NOT_NULL(x,y) ( Float.floatToIntBits(x) == Float.floatToIntBits(y) )\n"\
-"#define VALUE_IS_NULL(x) ( Float.floatToIntBits(x) == 0 )\n"\
+"#define VALUE_EQUALS(x,y) ( Float.floatToRawIntBits(x) == Float.floatToRawIntBits(y) )\n"\
+"#define VALUE_EQUALS_NOT_NULL(x,y) ( Float.floatToRawIntBits(x) == Float.floatToRawIntBits(y) )\n"\
+"#define VALUE_IS_NULL(x) ( Float.floatToRawIntBits(x) == 0 )\n"\
"#elif VALUE_CLASS_Double\n"\
-"#define VALUE_EQUALS(x,y) ( Double.doubleToLongBits(x) == Double.doubleToLongBits(y) )\n"\
-"#define VALUE_EQUALS_NOT_NULL(x,y) ( Double.doubleToLongBits(x) == Double.doubleToLongBits(y) )\n"\
-"#define VALUE_IS_NULL(x) ( Double.doubleToLongBits(x) == 0 )\n"\
+"#define VALUE_EQUALS(x,y) ( Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y) )\n"\
+"#define VALUE_EQUALS_NOT_NULL(x,y) ( Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y) )\n"\
+"#define VALUE_IS_NULL(x) ( Double.doubleToRawLongBits(x) == 0 )\n"\
"#else\n"\
"#define VALUE_EQUALS(x,y) ( (x) == (y) )\n"\
"#define VALUE_EQUALS_NOT_NULL(x,y) ( (x) == (y) )\n"\
=====================================
src/it/unimi/dsi/fastutil/HashCommon.java
=====================================
@@ -119,22 +119,29 @@ public class HashCommon {
}
- /** Returns the hash code that would be returned by {@link Float#hashCode()}.
+ /**
+ * Returns {@link Float#floatToRawIntBits(float)}.
+ *
+ * <p>
+ * Note that {@link Float#hashCode()} returns {@link Float#floatToIntBits(float)}.
*
* @param f a float.
- * @return the same code as {@link Float#hashCode() new Float(f).hashCode()}.
+ * @return {@link Float#floatToRawIntBits(float)}.
*/
-
public static int float2int(final float f) {
return Float.floatToRawIntBits(f);
}
- /** Returns the hash code that would be returned by {@link Double#hashCode()}.
+ /**
+ * Returns the upper and lower halves of {@link Double#doubleToRawLongBits(double)} xor'd together.
+ *
+ * <p>
+ * Note that {@link Double#hashCode()} would do the same with
+ * {@link Double#doubleToLongBits(double)}.
*
* @param d a double.
- * @return the same code as {@link Double#hashCode() new Double(f).hashCode()}.
+ * @return the upper and lower halves of {@link Double#doubleToRawLongBits(double)} xor'd together.
*/
-
public static int double2int(final double d) {
final long l = Double.doubleToRawLongBits(d);
return (int)(l ^ (l >>> 32));
=====================================
src/it/unimi/dsi/fastutil/Stack.java
=====================================
@@ -26,6 +26,8 @@ import java.util.NoSuchElementException;
* or even a more powerful {@link #peek(int)} method that provides
* access to all elements on the stack (indexed from the top, which
* has index 0).
+ *
+ * @param <K> the types of elements in the stack.
*/
public interface Stack<K> {
=====================================
src/it/unimi/dsi/fastutil/io/FastByteArrayOutputStream.java
=====================================
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2024 Sebastiano Vigna
+ * Copyright (C) 2005-2025 Sebastiano Vigna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package it.unimi.dsi.fastutil.io;
-import java.io.IOException;
-
import it.unimi.dsi.fastutil.bytes.ByteArrays;
/** Simple, fast byte-array output stream that exposes the backing array.
@@ -32,7 +30,6 @@ import it.unimi.dsi.fastutil.bytes.ByteArrays;
*
* @author Sebastiano Vigna
*/
-
public class FastByteArrayOutputStream extends MeasurableOutputStream implements RepositionableStream {
/** The array backing the output stream. */
@@ -87,7 +84,7 @@ public class FastByteArrayOutputStream extends MeasurableOutputStream implements
}
@Override
- public void write(final byte[] b, final int off, final int len) throws IOException {
+ public void write(final byte[] b, final int off, final int len) {
ByteArrays.ensureOffsetLength(b, off, len);
if (position + len > array.length) array = ByteArrays.grow(array, position + len, position);
System.arraycopy(b, off, array, position, len);
@@ -96,7 +93,7 @@ public class FastByteArrayOutputStream extends MeasurableOutputStream implements
@Override
public void position(final long newPosition) {
- if (position > Integer.MAX_VALUE) throw new IllegalArgumentException("Position too large: " + newPosition);
+ if (newPosition > Integer.MAX_VALUE) throw new IllegalArgumentException("Position too large: " + newPosition);
position = (int)newPosition;
}
@@ -106,7 +103,23 @@ public class FastByteArrayOutputStream extends MeasurableOutputStream implements
}
@Override
- public long length() throws IOException {
+ public long length() {
return length;
}
-}
+
+ /** @see java.io.ByteArrayOutputStream#toByteArray() */
+ public byte[] toByteArray () {
+ return ByteArrays.copy(array, 0, length);
+ }
+
+ @Override
+ public void close () {
+ // NOP: only to force no exception
+ }
+
+ @Override
+ public void write(final byte[] b) {
+ // Only to force no exception
+ write(b, 0, b.length);
+ }
+}
\ No newline at end of file
=====================================
src/it/unimi/dsi/fastutil/io/InspectableFileCachedInputStream.java
=====================================
@@ -189,16 +189,6 @@ public class InspectableFileCachedInputStream extends MeasurableInputStream impl
overflowFile.delete();
}
- @Override
- protected void finalize() throws Throwable {
- try {
- dispose();
- }
- finally {
- super.finalize();
- }
- }
-
@Override
public int available() throws IOException {
ensureOpen();
=====================================
src/overview.html
=====================================
@@ -215,8 +215,9 @@
abstract classes have been deprecated and are not listed here (they are no longer necessary due to
default methods in the corresponding interfaces).
- <div align=center>
- <table border=1 summary="Interfaces and Abstract Implementations" title="Interfaces and Abstract Implementations">
+ <div>
+ <table border=1>
+ <caption>Interfaces and Abstract Implementations</caption>
<tr><th>Interfaces<th>Abstract Implementations<th>Implementations
<tr><td>Iterable
<tr><td>Collection<td>AbstractCollection
@@ -253,8 +254,9 @@
<p>The following table summarizes static containers, which usually give rise
both to a type-specific and to a generic class:
- <div align=center>
- <table border=1 style="border: solid thin black" title="Static Containers" summary="Static Containers">
+ <div>
+ <table border=1 style="border: solid thin black">
+ <caption>Static Containers</caption>
<tr><th>Static Containers
<tr><td>Collections
<tr><td>Sets
=====================================
test/it/unimi/dsi/fastutil/objects/Object2IntOpenHashMapTest.java
=====================================
@@ -16,6 +16,7 @@
package it.unimi.dsi.fastutil.objects;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -215,5 +216,24 @@ public class Object2IntOpenHashMapTest {
public void testLegacyMainMethodTests() throws Exception {
MainRunner.callMainIfExists(Object2IntOpenHashMap.class, "test", /*num=*/"500", /*loadFactor=*/"0.75", /*seed=*/"383454");
}
+
+ /** Counts times hashCode() is called, so we can test double-hashing. */
+ private static final class HashCounter {
+ int hashCount = 0;
+ @Override
+ public int hashCode() {
+ hashCount++;
+ return super.hashCode();
+ }
+ }
+
+ // Regression test for https://github.com/vigna/fastutil/pull/337.
+ @Test
+ public void testMergeIntHashesKeyOnce() {
+ Object2IntOpenHashMap m = new Object2IntOpenHashMap(Hash.DEFAULT_INITIAL_SIZE);
+ HashCounter hc = new HashCounter();
+ m.mergeInt(hc, 0, Math::max);
+ assertEquals(1, hc.hashCount);
+ }
}
=====================================
test/it/unimi/dsi/fastutil/objects/Object2ObjectMapTest.java
=====================================
@@ -0,0 +1,27 @@
+package it.unimi.dsi.fastutil.objects;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class Object2ObjectMapTest {
+
+ @Test
+ public void testSmallMaps() {
+ assertTrue(Object2ObjectMap.ofEntries() instanceof Object2ObjectMaps.EmptyMap);
+ assertTrue(Object2ObjectMap.ofEntries(Object2ObjectMap.entry(new Object(), new Object())) instanceof Object2ObjectMaps.Singleton);
+ }
+
+ @Test
+ public void testThrowOnDuplicate() {
+ assertThrows(IllegalArgumentException.class, () -> Object2ObjectMap.ofEntries(
+ Object2ObjectMap.entry("dupe", "foo"),
+ Object2ObjectMap.entry("not a dupe", "bar"),
+ Object2ObjectMap.entry("dupe", "exception")
+ )
+ );
+ }
+
+
+}
View it on GitLab: https://salsa.debian.org/java-team/libfastutil-java/-/commit/c2513627b6e86ea5ce8a04e2727f41387850018f
--
View it on GitLab: https://salsa.debian.org/java-team/libfastutil-java/-/commit/c2513627b6e86ea5ce8a04e2727f41387850018f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20250819/c21f4da1/attachment.htm>
More information about the pkg-java-commits
mailing list