Releases: tommyettinger/jdkgdxds
1.6.2 "Wimbledonut"
This release rolls back the hash multiplier table changes from 1.6.1 and updates the hash multipliers to (probably) better ones. It doesn't do much else relative to 1.6.1, but I hadn't put a release out in a while here on GitHub... New features since 1.4.8 include:
- EnumMap and EnumSet, which are drop-in replacements for the classes with the same names in the JDK, but permit being initialized without a Class initially.
- Lots of new toString() and appendTo() code, making use of Java 8 language features to enable special formatting.
- Some bugfixes regarding equality on primitive sets, and maybe other primitive collections.
- The aforementioned hash multipliers change, from longs to ints, and using
BitConversion.imul()
on GWT to ensure the results stay sane.
This release has the distinction of being prompted by a dream. The dream was that a tennis tournament's scoreboard relied on jdkgdxds to store players attached to their scores or rankings, but certain small rankings produced a noticeable delay in processing and I needed to try to fix the scoreboard mid-tournament. I suppose it's a change of pace from the dreams where I'm knife-fighting shadow demons or piloting airships through waterfalls.
1.4.8 "Array of Sunshine"
This release started out being needed to fix a bug in the deque types, when the initial capacity was 0. It soon expanded to include many new overloads of addAll, removeAll, containsAll, containsAny, and sometimes removeEach, all able to take array or range of array (with an offset and length) arguments. From 1.4.7, there's more constructors available for FilteredString types. They also use a faster hashing algorithm that may also be better for the limited needs FilteredString sets and maps have. The dependency on digital is now up to 0.4.7 .
[1.4.8]
- Deque types can be initialized with capacity 0, and now won't suddenly crash when an item is added.
- Almost every type got some new methods, thanks to PrimitiveCollection adding overloads that take arrays or ranges of arrays.
- The above change was also applied manually to Object-based Collection types.
- Where appropriate, types have removeAll() and removeEach(), as well as containsAll() and containsAny().
[1.4.7]
- The dependency on digital was updated to 0.4.7, which adds some potentially useful features, and has many more null checks.
- Filtered sets and maps have the full range of constructors that maps and sets usually have, now.
- The Filtered-String sets and maps use a different hashing algorithm now that takes advantage of how small a char is relative to a long.
1.4.6 "Yes Filter"
This release mostly exists so the FilteredString Sets and Maps can be serialized. But wait, I haven't done a release with those classes yet! To recap, here's the changelog (in reverse order...):
[1.4.6]
- [BREAKING CHANGE] The Filtered-String sets and maps now use a CharFilter object to group their filter and editor, allowing them to be serialized and deserialized.
[1.4.5]
- The dependency on digital was updated... again... to 0.4.5, though this time it brings several new features. None used here.
- Filtered-String sets and maps! These are like the CaseInsensitive ones, but allow configuring how characters are used and modified.
- Filtered-Iterable sets and maps, too! These are like the Filtered-String ones but work on an Iterable of sub-items instead of a String of characters.
- FilteredComparators provides ways to sort the ordered filtered types.
- NumberedSet.addOrIndex() was broken, and now is fixed.
- Nullity annotations were put in the right places pretty much everywhere.
- I think this is the point Gradle was updated to 8.5; nothing broke, and it shouldn't affect user projects.
[1.4.4]
- The dependency on digital was updated again to 0.4.3 because of a break in GWT compilation in digital 0.4.2; it is fine now.
[1.4.3]
- The dependency on digital was updated to 0.4.2, which includes
BitConversion.countTrailingZeros()
; we use it in OffsetBitSet. - A bug in getAndIncrement() for ordered maps with int and long keys was fixed; before, it didn't handle zero keys correctly.
- The
Utilities.longHashCodeIgnoreCase()
methods now are much closer to howHasher
implements them in digital; the results are different.
[1.4.2]
- The dependency on digital was updated to 0.4.1, which includes a new
BitConversion.countLeadingZeros()
method that we use here to speed things up on GWT a bit. - The dependency on checker-qual was updated to 3.39.0, which shouldn't break or really even change anything here.
[1.4.1]
- [POSSIBLE BREAKING CHANGE] The dependency on digital was increased to 0.4.0, and that version changes what
Hasher.hash()
andHasher.hash64()
return for the same arguments. This doesn't affect jdkgdxds code, but may affect users who rely on digital transitively. - New
ObjectList.sortJdk()
method will use the defaultList.sort()
method rather than the in-place mergesort used byObjectList.sort()
. - Updated to Gradle 8.3 and Checker Framework 3.37.0 .
So, there's a lot that has changed since the last release here on GitHub, but new releases have been published to Maven Central all this time. Mostly new are the four FilteredString types and the four FilteredIterable types. I have no hope of serializing FilteredIterable (Ordered) (Set/Map), so those will just be treated as unserializable (at least, to JSON) due to their use of functional interfaces. However, FilteredString (Ordered) (Set/Map) classes can be serialized using jdkgdxds-interop or (soon) kryo-more. This takes advantage of how, starting in 1.4.6, you can register CharFilter types by name, and ser/deser uses that name to get the right CharFilter. But what even is a CharFilter?
A CharFilter is used by each of the FilteredString classes to use a filter to potentially ignore some characters in a String item/key, and an editor to potentially change the characters that aren't ignored (but not destructively editing). A common use for the editor is to convert every character to upper-case if possible (typically using Character::toUpperCase
), which makes the FilteredString class act like one of the existing CaseInsensitive ones. You can go further and use the filter to only consider letter characters by using Character::isLetter
as the filter, or only alphanumeric chars with Character::isLetterOrDigit
.
There's similar behavior in the FilteredIterable types, but instead of a FilteredString type works on a String made of chars, a FilteredIterable works on an Iterable of a generic sub-item type. You still have a filter that can exclude sub-items and an editor that can make a different sub-item get used. I don't expect FilteredIterable types to be used as much as the String ones.
Well, there's that release!
1.4.0 "Controlled Fusion"
This release includes the ability to combine whole maps according to a value-merging function (like the existing merge()
does for single values in some map types). The merge()
method is sometimes present, but now only when it acts how it is documented in the JDK -- if it can't remove values as well as add them, the similar method is called combine()
. This is somewhat of a breaking change, since merge() has changed to combine() in some classes that optionally implemented it; all of these classes had primitive keys or values and didn't actually implement Map
. To avoid JDK8 functional interfaces, which are undefined on RoboVM, each combine() implementation takes a functional interface defined by funderby. Also new are no-arg with() methods on most map types, meant for code-generation situations where the amount of arguments isn't known beforehand.
The release also fixes some dependency issues (actually done in 1.3.1, which removed unnecessary sources deps, and 1.3.2, which updated the digital dependency to work on GWT). In the test sources, which you would need to access from this repo and not from a JAR download, there are now enum-keyed maps and sets. I didn't think these were significant enough to warrant inclusion in the main repository, since an Object-keyed map can use enums just fine, but if you want the classes, they're a tiny bit more efficient.
1.3.0 "Robo Revolt"
This release is meant to ease compatibility with RoboVM, and it does so by removing usage of interfaces defined only in Java 8 or higher. Language level 8 is still required, since we use default methods heavily, among other niceties in 8. This updates to Funderby 0.1.1 and stays using digital 0.2.0. See the updating section in README.md for notes on what needs changing.
1.2.2 "The All Clear"
We have Bags! These are just like the List classes, and each extends its counterpart List, but the Bags are unordered, and have faster deletion (from any index) as a result. These were the main thing added in 1.2.0 . I screwed up ObjectList.equals()
, and then fixed it! That fix happened in 1.2.1. I screwed up clear()
on all primitive-keyed maps, and they would never properly remove the zero key or its value! That happened a long time ago, but the fix only happened just now, in release 1.2.2 .
1.1.3 "A Series Of Tubes"
This release is extremely minor on its own, but updates the release I forgot to post on GitHub before it (1.1.2 is on Maven Central, though). The release before this is actually significant for GWT, so I'll summarize it here. The GWT inherits
lines have now changed to include com.github.tommyettinger.
in the packages, because without a package, all sorts of very strange problems could occur in code that used jdkgdxds or its dependencies. Other than that change from 1.1.2, 1.1.3 updates digital to 0.1.8 and checker-qual to 3.30.0 , and not much else. It seems like jdkgdxds is pretty stable now in terms of API, and I think that's good!
1.1.1 "Table Flip"
This release is not especially small, but isn't huge either.
- It adds IdentitySet (and its Ordered variant).
- It fixes some bugs in HolderSet and CaseInsensitiveMap.
- Most of these are in HolderSet, and affect various operations that take a T or K object but were coded to take a K or T.
- Both had their
equals()
fixed.
- It makes the inner Entries, Keys, and Values types of various maps all implement
equals()
correctly (I hope it's correct, at least; there isn't a standard to go by in the JDK). - It changes the internal hash mixing (again) so it should always use a relatively high-quality multiplier, chosen from a table of 512 numbers.
- The only hash multiplier used in libGDX is
0x9E3779B97F4A7C15L
, which mathematically should do extremely well, but has a caveat that it collides frequently when used to mix hashCodes that are Fibonacci numbers. With enough items, Fibonacci numbers tend to show up, and then that only multiplier becomes a liability. - Switching between hash multipliers when we
resize()
means no extra work has to be done to re-hash existing items (only the re-hashing that has to be done during resizing already). Since any situation with hash flooding would causeresize()
to be called, changing our multiplier (and thus changing any weakness) only there seems to work.
- The only hash multiplier used in libGDX is
- It switches from the ancient JSR305 nullity annotations to the newer, well-maintained checker-qual annotations.
- This is a breaking change if you used JSR305 annotations, because jdkgdxds no longer provides them as a transitive dependency. Migrating to checker-qual isn't hard, and can mostly be done with find-and-replace.
Nonnull
needs to be changed toNonNull
, and so on.
- This is a breaking change if you used JSR305 annotations, because jdkgdxds no longer provides them as a transitive dependency. Migrating to checker-qual isn't hard, and can mostly be done with find-and-replace.
That should be everything. Happy New Year!
1.1.0 "Merry JDKGDX-Mas!"
Christmas came early, it looks like, with... what could be a disappointing stuffing for your stocking. Unless you like niche features, that is, or bit sets (which are also a niche feature). On the plus side, there's a few potential bugs squashed here, so there's no reason to avoid an update. Some important things to note:
- OffsetBitSet is new; it acts like a primitive collection of ints, but starts counting at a specified offset (which can be negative, but defaults to 0). It only uses one bit per int it stores, but also requires one bit for every int in the range it doesn't store. For dense int sets with a known range, it makes sense.
- There have been numerous improvements to iterators and other less-often-considered parts of sets and maps.
- You can get the remaining items from an iterator appended into a Collection (or PrimitiveCollection) of the appropriate type using
appendInto()
. - You can also get those remaining items as a new list with
toList()
. - You can always set the position of a map or set iterator, using
reset()
, or one of its inner Keys, Values, or Entries data structures, usingresetIterator()
.
- You can get the remaining items from an iterator appended into a Collection (or PrimitiveCollection) of the appropriate type using
- There's various improvements to toString() and appendTo(), which appends from a set to a StringBuilder.
- The dependency on digital is now 0.1.5; the suggested (but not necessary) dependency on juniper is 0.1.7 or higher.
This is mostly release 1.1.0, suggesting it is more major, because I should have given the previous release a more "major" version number, but didn't. This is actually a fairly minor update compared to some earlier releases, since it mostly fills in missing functionality without changing much.
1.0.5 "Double-Ended BOO!"
Just before Halloween, we have a new release that exorcises iterators and gets the deques nice and shining. All of the list iterators and deque iterators, plus NumberedSet's iterator, now handle removal via iterator correctly, as well as add()
and set()
when using an iterator as a ListIterator or its primitive equivalent. The deques needed a lot of code changed, because several key methods (including addLast()
) didn't always work. Deques also have an insert()
method now (which is equivalent to calling add()
with an index argument), which is used by the new iterators they have.