Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.97a is out! (02/02/24); New blog post: Simulator Enhancements (03/13/24)

Author Topic: Today I learned that in Java, Maps are not Collections...  (Read 1184 times)

Sundog

  • Admiral
  • *****
  • Posts: 1723
    • View Profile
Today I learned that in Java, Maps are not Collections...
« on: October 17, 2019, 11:58:15 PM »

My CS professor told me that maps are collections. I'm pretty sure maps are considered collections in every other language I've used. I thought it was a safe assumption to make. I was wrong. Am I alone in thinking this is completely bonkers?

https://stackoverflow.com/questions/2651819/why-doesnt-java-map-extend-collection

SomeDegenerate

  • Ensign
  • *
  • Posts: 15
  • Credit to TerminalMontage on YouTube for the PfP
    • View Profile
Re: Today I learned that in Java, Maps are not Collections...
« Reply #1 on: October 18, 2019, 11:29:27 AM »

Just gone over that same deal in my own Java course. I wouldn't focus on it too much, the only functional difference you'll notice is some occasional differences in the methods you'll call (for example, Maps have their own foreach loop).

All of the following is speculation, but I'd say that Oracle made the decision to have Maps not extend Collection for functionality reasons. You can see this in the documentation - Collection and Map have many of the same methods, with differences like a lack of a toArray() and contains() method in Map and the inclusion of a containsKey() and entrySet() method in Map. If you think about it in the context of Java's class structure, this makes sense: when you call contains() on a Map, would you want to check keys or values? When you attempt to call toArray() on a Map, how will that work, given that Map has two entries for every one that would be in an array? It's easier to compartmentalize it and have Map only be able to input and output in a certain way.

Plus there's the fact that Oracle in general and Java in particular do their own thing. Always have, and I doubt that'll ever change :P

At any rate, please do take what I said with a grain of salt - while I've been working with Java for years I'm self-taught, meaning that if I ever didn't understand something that I needed chances are I just changed my program such that I didn't need it or copy+pasted someone else's code off of stackoverflow. And, as I'm sure you guessed by the fact that my Java course is only just going over data types in Java, I've only just started my formal education in CS. I'm just as likely to be full of *** as spot on.

Cheers!

tl;dr: Because of the way Java's class structure works it's more convenient to keep Collections and Maps separate. Probably.
« Last Edit: October 18, 2019, 11:32:41 AM by SomeDegenerate »
Logged
Roses are red, violets are blue. I'm complete garbage, how about you?

Alex

  • Administrator
  • Admiral
  • *****
  • Posts: 23988
    • View Profile
Re: Today I learned that in Java, Maps are not Collections...
« Reply #2 on: October 18, 2019, 01:35:55 PM »

My CS professor told me that maps are collections. I'm pretty sure maps are considered collections in every other language I've used. I thought it was a safe assumption to make. I was wrong. Am I alone in thinking this is completely bonkers?

https://stackoverflow.com/questions/2651819/why-doesnt-java-map-extend-collection

Hmm, that's interesting. I can see your point! I'll just say that I maybe had to iterate over the entry set of a map... probably significantly less than once a year.

And, consider that both Map and Collection have a remove(Object) method, which would not function in a compatible way if a Map was a Collection of key-value pairs. So given that, and the limited utility of this, I can see why they'd opt for a .entrySet() method instead of having to rename a core method like remove() in one of the interfaces.
Logged

Sundog

  • Admiral
  • *****
  • Posts: 1723
    • View Profile
Re: Today I learned that in Java, Maps are not Collections...
« Reply #3 on: October 18, 2019, 03:39:48 PM »

Collection and Map have many of the same methods, with differences like a lack of a toArray() and contains() method in Map and the inclusion of a containsKey() and entrySet() method in Map. If you think about it in the context of Java's class structure, this makes sense: when you call contains() on a Map, would you want to check keys or values?
And, consider that both Map and Collection have a remove(Object) method, which would not function in a compatible way if a Map was a Collection of key-value pairs.
Good points! There are definitely practical differences between maps and things like lists or stacks, but I would think the best solution for that would be to have a separate interface for methods (toArray/contains/remove) that don't apply to all collections (or perhaps I should call them data structures?). The fact that the Map and Collection interfaces have so many methods in common seems like a clear indicator that they should have a common ancestor.

Anyway, I'm generally very happy with Java's HashMap class, and calling entrySet on the rare occasion when I need it doesn't bother me at all. Really, I'm just bitter because I thought I could rely on (myVar instanceof Collection) returning true if myVar is a map. Now that I know that's not the case it won't be a problem, but figuring it out was... not enjoyable.

SomeDegenerate

  • Ensign
  • *
  • Posts: 15
  • Credit to TerminalMontage on YouTube for the PfP
    • View Profile
Re: Today I learned that in Java, Maps are not Collections...
« Reply #4 on: October 18, 2019, 05:00:57 PM »

I would think the best solution for that would be to have a separate interface for methods (toArray/contains/remove) that don't apply to all collections (or perhaps I should call them data structures?). The fact that the Map and Collection interfaces have so many methods in common seems like a clear indicator that they should have a common ancestor.

You know, you're absolutely right: that would have been another, perfectly valid way to set the language up. Another way to handle the issue - at least, most of the issues - would have been through method overloading, where you could, say, feed the method that would have to behave differently your Map object as a parameter. This has its own set of problems, but I digress.

The point is that there are several ways they could have handled the issue, and they probably chose the option they did to minimize the work on their end. Providing a separate interface for each of your collections - which would require you to write many identical methods, if I'm going through this correctly in my head - when all of your collections EXCEPT Map behave the same in the context of those methods is inefficient. Why not instead compartmentalize Map as its own class since it's the only collection that behaves radically differently from the others, then justify it with some mumbo-jumbo about how Maps aren't really a collection?

I know that if I had just spent hours trying to put together a Collection class and there's this ONE COLLECTION that isn't behaving properly because it needs some SPECIAL METHODS and I can't figure out how its DUMB, STUPID SELF is supposed to play nice with some of the methods that all of my other collections have in common I would be liable to say "*** it, I'm making a separate class, John over in HR can deal with it."

Of course that's mildly facetious, but you have to poke fun at Java every once in a while to stay sane  ;D

Really, I'm just bitter because I thought I could rely on (myVar instanceof Collection) returning true if myVar is a map.

Oooooh, yeah, that is not fun. At least you've got it now though, and congrats for figuring out on your own what the problem was! You're a more patient man than I!

Mind if I ask what it was for? I'm a bit of a fan of your work, especially the Starship Legends mod. That added some excellent flavor to the ships, and fantastic lasting consequences of performance, IMO.
« Last Edit: October 18, 2019, 05:02:48 PM by SomeDegenerate »
Logged
Roses are red, violets are blue. I'm complete garbage, how about you?

Sundog

  • Admiral
  • *****
  • Posts: 1723
    • View Profile
Re: Today I learned that in Java, Maps are not Collections...
« Reply #5 on: October 18, 2019, 11:24:51 PM »

The point is that there are several ways they could have handled the issue
Very true. I'm sure the people who made the decision had plenty of good reasons. The fact that it rubs me the wrong way is a pretty insignificant downside.

Providing a separate interface for each of your collections
Oh, yikes, that's not what I meant to suggest at all! That would pretty much defeat the purpose of using an interface at all, right? I was talking about something more along the lines of this:
Collection (intended for all classes that meet wikipedia's definition of Collection)
Map extends Collection (with methods like containsKey and entrySet)
SimpleCollection extends Collection (with methods like toArray, contains, and remove)
List extends SimpleCollection

I know that if I had just spent hours trying to put together a Collection class and there's this ONE COLLECTION that isn't behaving properly because it needs some SPECIAL METHODS and I can't figure out how its DUMB, STUPID SELF is supposed to play nice with some of the methods that all of my other collections have in common I would be liable to say "*** it, I'm making a separate class, John over in HR can deal with it."
lol yeah, I've been there.

Of course that's mildly facetious, but you have to poke fun at Java every once in a while to stay sane  ;D
Heh, yeah, that certainly helps, but it's not the only way. I've heard switching to Kotlin helps quite a bit on the sanity front   ;)

Mind if I ask what it was for?
My failure to understand that java doesn't think of maps as collections (along with several other shortcomings on my part) resulted in the ill-fated release of starship legends 1.3.5, which assigned null to most of its maps. The results were predictable. The NPEs were numerous. I have no idea how I managed to dodge them while testing.