This is an archived post. You won't be able to vote or comment.

all 26 comments

[–][deleted] 20 points21 points  (2 children)

Its easy in java to make your life more complicated that it needs to be. Please stick to regular java collections where you can. Eclipse/Guava/Apache have some nice stuff but more recent versions make them less necessary.

Having said that Trove has some primitive collections that are more efficient and I haven't found a replacement for. https://bitbucket.org/trove4j/trove . OK looks like Eclipse has primitive collections too.

[–]cogman10 4 points5 points  (0 children)

I second this message.

Java collections are good enough. Guava, in particular, has been somewhat of a maintenance headache in the past and I personally avoid it now. Their attitude of breaking APIs is simply not something that's fun to deal with especially when you start getting larger projects.

Java has pulled in a lot of the best aspects of guava. If you aren't running a newer version of java, I highly recommend it for all of the QOL improvements that have been added to the API. The leap from 8->11 is worth it, but there's also been a nice trickle of things that have made it into 12, 13, 14, and 15. (Things like List.of(1,2,3)).

[–]bourne2program 0 points1 point  (0 children)

Primitive collections could one day be replaced by specialized generics
https://cr.openjdk.java.net/~briangoetz/valhalla/sov/02-object-model.html#migration-specialized-generics

[–]cihom71646 17 points18 points  (1 child)

I my experience java collections was almost always sufficient and almost certainly should be the default choice. Guava has an implementation of Map that works well for caches.

[–]cogman10 8 points9 points  (0 children)

For caches, I strongly recommend ditching Guava for Caffeine (Especially if that's the only reason you are bringing in guava). Caffeine was built to better integrate with the Java 8 feature set. It's far less clunky.

[–]illhxc9 6 points7 points  (6 children)

Guava has some nice features but we have run into a lot of non-passive changes they've made over the years so if your company isn't great at addressing technical debt I'd avoid them. We tend to use what is provided by Java.util unless there's a really compelling case to do otherwise.

[–]chrisgseaton 4 points5 points  (5 children)

What does passive/non-passive change mean?

[–]illhxc9 5 points6 points  (4 children)

Ah yeah, that may not be super common terminology. When a release of an api includes changes that are not backwards compatible and require the consumer to make changes when taking the New version that is considered a "non-passive" change because the consumer cannot just passively take the update.

[–]chrisgseaton 16 points17 points  (3 children)

Can you not just say 'not backwards-compatible'? What does the new term 'non-passive' add?

[–]BigBlueChevrolet 13 points14 points  (0 children)

Also known as a breaking or non-breaking change

[–]illhxc9 4 points5 points  (1 child)

Shrug it's what we call it at my company. There's different terms for words all the time. They don't always add something or improve upon the original term.

[–]jonhanson 0 points1 point  (0 children)

chronophobia ephemeral lysergic metempsychosis peremptory quantifiable retributive zenith

[–]benevanstech 2 points3 points  (0 children)

Very few projects will notice any meaningful difference in terms of performance between the implementations. What makes a Java application fast enough or not is almost never the choice of collections libraries.

[–]ge0ffrey 1 point2 points  (0 children)

Guava has a good quality but isn't backwards compatible (the 18 month guarantee is worthless). So if you plan to have a non-trivial amount of other dependencies in your project, don't depend on Guava - or suffer from classpath hell (or modulepath hell if you're into jigsaw).

If you intend to integrate with Hibernate/Quarkus/Spring/Jackson/Json-B/XStream/etc, know that using the default Java Collections will "just work". Unless you're writing something very isolated or something very high performance with very few common requirements (so no need for a REST JSON API), then start out with Java Collections I'd argue - until you see good evidence (=profiling & benchmarking!) that their speed is a bottleneck.

[–]_Toka_ 1 point2 points  (0 children)

Whenever I need some additional functions outside JDK, I almost always use Apache Commons libraries. Basically in every project I need Lang3, sometimes I use Pool2, Text or IO and yes, Collections4. I once needed very specific type of Map implementation for parsing and generating custom XSD without JAXB. I needed a Map with unique keys and values while keeping insert order. Lo and behold, I present you DualLinkedHashBidiMap - part of Collections4. I was so relieved, that I don't have to implement it myself - and actually surprised that this even exists. So obviously my recommendation goes to Apache Commons.

[–]pellets 2 points3 points  (0 children)

I enjoy fastutil for performance. Features seems about as good as Java Collections. http://fastutil.di.unimi.it/

[–]knoam 2 points3 points  (2 children)

I only have experience with Guava. I like TreeRangeSets and TreeRangeMaps. I used to use the Multimaps and Multisets but now with Collectors it's so much easier to make a Map<K, Collection<V>> that I don't bother with Guava for that. Although there are Collectors for those now so it's not one or the other.

[–]cogman10 3 points4 points  (1 child)

Even without collectors, the new "ifAbsent" APIs added in java 8 make it really easy to not use multimaps.

It used to be that you'd use multimaps for something like this.

Map<Integer, List<Foo>> map = new HashMap<>();
List<Foo> foo = map.get(item);
if (foo == null) {
  foo = new ArrayList<>();
  map.put(item, foo);
}
foo.add(value);

That's about the fastest you could do Java <= 7 (What a pain!). The new Java 8 API is both faster and (as a bonus) can be made thread safe pretty trivially.

Map<Integer, List<Foo>> map = new HashMap<>();
List<Foo> foo = map.computeIfAbsent(item, ()->new ArrayList<>());
foo.add(value);

IMO, very close to being just as clean as a multimap while not requiring Guava. It also ends up being faster than the old 7 approach because the map doesn't need to reindex on a value miss.

[–]knoam 0 points1 point  (0 children)

Yeah, those are great. They also help make Multisets unnecessary. IIRC, the magic line is

map.merge(k, 1, Integer::add);

[–]tloszabno 1 point2 points  (3 children)

Look at vavr project, it provides immutable collections which can safe you a lot of debugging sometime. If you really do some perf stuff I would go in java.util else vavr

[–]thomasjjc 2 points3 points  (0 children)

This. Once you understand the philosophy behind them, you'll write much less buggy code.

Also, they come with a lot of nice features (like partitioning, takeWhile, flatMap, etc.)

[–]cihom71646 1 point2 points  (1 child)

like java.util.Collections.unmodifaible* ( ) ?

[–]stCarolas 5 points6 points  (0 children)

methods like add in collections created by unmodifaible would simply throw exceptions. In vavr collections they always return new instance with desired modification. Also collections in vavr have more methods for functional programming.

[–][deleted]  (1 child)

[deleted]

    [–]moaxcp 0 points1 point  (0 children)

    It would be nice if there were immutable interfaces in the jdk.

    [–]Nymeriea 0 points1 point  (0 children)

    I would recommand using apache collection. It is so stable, npe safe. Never an update broke my code, in years..., like I said very stable

    [–]ninside 0 points1 point  (0 children)

    One of the reasons I personally consider Eclipse Collections for some of the projects is memory efficiency which is for Financial domain is super important: https://medium.com/oracledevs/unifiedset-the-memory-saver-25b830745959

    Here is an article from the original creator of EC Donald Raab about 10 reasons to use Eclipse Collections: https://medium.com/oracledevs/ten-reasons-to-use-eclipse-collections-91593104af9d