Win a copy of Java 9 Modularity: Patterns and Practices for Developing Maintainable Applications this week in the Java 9 forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Why can't I make an array of ArrayList?  RSS feed

 
Jim Venolia
Ranch Hand
Posts: 312
2
Chrome Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've googled enough to a)  find out Java really doesn't want me to do this; and b) find workarounds that generate javac warnings.  Which in my mind are errors.

First question.  I need an array of 2 ArrayLists, each ArrayList contains bytes.  Something like

This won't compile, don't try.  Ideas on how else to do it?  The code using them will be something like:

See this to see why.

So, ideas for other ways to do this?

Second question, and I have a sneaking suspicion I'm not gonna understand the answer.  Seems I can't create Arrays of Paramterized Types.  Why not?  Seems like a perfectly cromulent thing to do, given I really like the <type> notation I learned about a couple days ago.  ArrayList<byte> is an object.  I'm supposed to love and support objects.  Things I love and support are not supposed to bite me in the butt when I most need them.



 
Jim Venolia
Ranch Hand
Posts: 312
2
Chrome Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
We should be able to edit our posts for 5-10 minutes after posting them.  2 things.

1)  Yeah, I can have 2 for loops, one for foo[0] and one for foo[1].  Clumsy.  Sad.
2)  I understand what the link to 'why I can't create arrays of parameterized types' is telling me.  What I don't understand is the why behind it.   As I've never learned anything of compilers past "man gcc", I suspect I won't understand the answer.
 
Dave Tolls
Ranch Foreman
Posts: 2996
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


That's an array of a List of ArrayLists, not an array of ArrayLists.
 
Piet Souris
Rancher
Posts: 2014
71
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Jim,

can't help reading about your love-hate relationship with Java with a big grin on my face... sorry!

But why still use arrays? They lack so much flexibility.

This looks much easier:
 
Stephan van Hulst
Saloon Keeper
Posts: 7927
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can explain the 'why'. Java arrays are covariant, and they can not be made invariant. Java collections are invariant by default. Collections and arrays do not play together nicely.

What does this mean? Covariance means that you can assign a collection or array of elements of one type to a collection or array of elements of a less specific type. Here's an example:
You can not do this with Collection types by default:

Generics was introduced to improve type safety. Mixing them with arrays breaks that type safety:

Even though we properly parameterized all our generic types, we were still able to get a ClassCastException, something that generics were intended to prevent. That's because we were able to create a covariant array of an invariant collection.

The designers could have made this a warning instead of an error, but what would be the point? When you create an array of a parameterized type, you're saying: "I want type safety and I don't want type safety". That doesn't make sense. If you really want to do this and get a warning instead, you can just use raw types:
 
Campbell Ritchie
Marshal
Posts: 56187
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim Venolia wrote:. . .This won't compile . . .
Piet Souris wrote:. . .
There is a difference: B/b. You cannot make Lists of primitives, but must box them to the corresponding wrapper objects.

Go through the Java™ Tutorials and look for the sections about generics: there are two: This is the second. It has to do with arrays being covariant and generics being invariant, but I haven't got enough time to explain any more now.
 
Campbell Ritchie
Marshal
Posts: 56187
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arrays are covariant: if T is a subtype of S then a T[] is a subtype of an S[].
Arrays are programmed into the javac tool on the assumption that programmers know what they are doing and always program code correctly. Try the following code which demonstrates that 3 is boxed into an Integer and that an Integer is a subtype of Number and that an Integer[] array can be assigned to a Number[] reference.Try running that code: no imports necessary.
You can see in line 1 that the three ints are boxed into Integers; you can see in line 3 that an Integer[] (again using boxing) can be assigned to a Number[] reference and line 5 shows that the compiler will permit me to insert the double 123.45 into the array because it is a Number (when boxed). Goodbye type‑safety. Well actually, before generics, that sort of thing was never type‑safe in the first place.

Now, we all know that a List<Integer> ISN'tT‑A List<Number> and is not a subtype of it. But  List<Integer> is a subtype of List<? extends Number>. We also know that the intention of generics is to make code type‑safe. We also know that the post‑Java5 compiler is programmed on the basis of Murphy's Law:-
Whatever can go wring, will go wrong.
Now, let's imagine you have four Lists:-Output:-
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [1.23, 4.56, 7.89]]
Now, what if you wrote this:-Since a List<Integer> and a List<Double> are both subtypes of List<? extends Number>, what is stopping you from assigning lists[1] to list4? Isn't is obvious that this will breach type‑safety? Since the idea behind generics is a higher level of type‑safety than existed in JDK1.4.2, the javac tool is programmed to refuse that sort of assignment, by making it impossible to create an array of any type with <> in its name:-
 
Jim Venolia
Ranch Hand
Posts: 312
2
Chrome Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, I knew I wouldn't understand the answer   Too many of these concepts are new to me in JavaLand, I know the pieces but can't quite put them together.

I did order the OCA/OCP Java SE Programmer Study guide from Amazon and it should arrive today.  I suspect that will truly overwhelm edumacate me.

An array/list/whatever of ArrayType<byte> would be very useful, but I suspect my time is better spent coming up with another way.

Thanks for the replies.
 
Campbell Ritchie
Marshal
Posts: 56187
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim Venolia wrote:Yeah, I knew I wouldn't understand the answer   Too many of these concepts are new to me in JavaLand . . .
Practice, practice, practice. As you write things, and show us them, you will gradually come to understand them.
An array/list/whatever of ArrayType<byte> would be very useful . . .
There are several answers to that:-
  • 1: It ain't never gonna happen.
  • 2: You can't have Lists of primitives. You can however have Lists of wrapper types and use boxing conversion.
  • 3: What use are bytes? They are too low‑level for anything other than sending across networks. Think higher‑level.
  • Thanks for the replies.
    That's a pleasure
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    The Objects I'm working with happen to be bytes.  Wrapping them in Bytes is fine.  Wrapping them in Chars, Strings, or Integers is 99% guaranteed to result in toothmarks where I sit.
     
    Piet Souris
    Rancher
    Posts: 2014
    71
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Have you ever considered working with BitSets? (see the API). These things have useful methods for or-ing, and-ing, counting the number of 1 bits, et cetera. Ideal maybe for things like cryptopals?
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Houston, we have a winner:


    Never heard of bitsets, I'll look into them.  Thanks!
     
    Piet Souris
    Rancher
    Posts: 2014
    71
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Well done! Enjoy a pie.

    Does my example (click) make more sense now?
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks for the pie.  Yeah, once I realized doing the obvious was verboten I looked at your example and figured out my final answer.

    The final result?  I realized I could convert my byte[] into a string, then use substring() to make my 2 arrays.  Have yet to see if that's a viable solution, and am tempted to ask "can my string contain any 8 bit value 0-0xff as long as I don't try to print it, or am I leaning on a wall waiting for a blindfold and cigarette?".  Near as I can see a char is a 16 bit viable unicode doohicky, as I live in the USA learning unicode is akin to learning Mandarin Chinese.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7927
    143
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That's not good. Abusing strings to get some bytes into a collection is very confusing and leads to brittle and unclear code. Why are you bent on getting a nested collection of bytes in the first place? What problem are you trying to solve?
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That's what I was afraid of.

    My problem is here.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7927
    143
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Okay, so I'm guessing the part you're dealing with is breaking the input up into blocks of bytes and then transposing the blocks.

    Transposition is a fairly standard matrix operation. I suggest you write a ByteMatrix class that is internally represented by a byte[][] and has a height() property, a getRow(int index) method, a transpose() method, and a read(int width, InputStream bytes) factory method. The transpose() method returns another ByteMatrix, while the getRow() method returns a ByteBlock that simply wraps around a byte[]. You can add a getDistance(ByteBlock other) method to the ByteBlock class that calculates the distance between two blocks.
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Can I assume the above thread is also why I can't create an array of StringBuilders?  Or should I google some more to figure out what I'm doing wrong.
     
    Campbell Ritchie
    Marshal
    Posts: 56187
    171
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jim Venolia wrote:Can I assume the above thread is also why I can't create an array of StringBuilders?  . . .
    No. StringBuilder isn't a parametrised class, so there shou‍ld be no problem putting its objects into an array.
    Why you would want a StringBulder[], now that is a different question.
     
    Jim Venolia
    Ranch Hand
    Posts: 312
    2
    Chrome Linux VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This.  I'll keep googling, guess I was doing something stupid.
     
    Consider Paul's rocket mass heater.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!