• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Bear Bibeault
  • Liutauras Vilda
  • Devaka Cooray
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • Henry Wong
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

Java Challenge is confusing

 
Greenhorn
Posts: 9
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi folks,

Been absolute ages since I went on this website. Currently going through Generics in Java (https://hyperskill.org/learn/step/2641) and I got stuck at a code challenge question. It's a challenge following information about Generics and Wildcards.




Code Challenge — Write a program
You are provided with the backbone of ListMultiplicator class that has multiple methods that take list and multiplies its content specified number of times. The original list content should be changed after method returns. The task is to add implementation to the method without changing its signature.


You are guaranteed that:

list is not null
n equals or greater than zero
n stands for the number of times the original list repeated in the result. So if n equals zero the resulting list should be empty.

For the original list:

[1, 2, 3]
and n equals 2 the result should be:

[1, 2, 3, 1, 2, 3]




From what I gather from the hints tab, you can use a helper method to store the original array. However, I'm just completely lost on writing the logic for this challenge after about an hour. If anyone could be of use to explain how to solve it, that'd be great!
 
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Multiplication is done in regards to original list ? What do I mean by that:

With list = [1, 2, 3] and n = 3 result should be [1, 2, 3, 1, 2, 3, 1, 2, 3] or [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] ?

In first scenario, you are always adding original list, in second, you multiply copy all items from previous iteration.

 
Miroslav Lehotsky
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Either way, it's quite simple. First solution that comes to mind, consider first checking argument 'n'. Then based on the value, make a copy of the original list and call 'addAll' on original list 'n' times in cycle.


This is for the first scenario mentioned by me (using copies of original list), for second scenario, you would need to add multiplications of the originalListCopy to originalList in each iteration. Don't know what is the required behavior for n = 0.

Watch out to make really a copy of originalList, not only another reference to the same list.
 
Miroslav Lehotsky
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, for second scenario it could be even better, by not using copy of the original list at all, and just append by addAll to the originalList same originalList, eg: originalList.addAll(originalList).
 
Marshal
Posts: 67939
258
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslav Lehotsky wrote:. . . using copies of original list . . .

Do you think that is a copy, as you asked?

[addition]

Miroslav Lehotsky wrote:. . . originalList.addAll(originalList).

Please explain whether that will work correctly.
 
Miroslav Lehotsky
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Do you think that is a copy, as you asked?



If you're referring to code, it's just pseudocode, that's why I added that last sentence there...

Please explain whether that will work correctly.



Ok, I see now, it's not safe operation this way according to API documentation, mentioning:


...The behavior of this operation is undefined if the specified collection is modified while the operation is in progress.  (Note that this will occur if the specified collection is this list, and it's nonempty.)



Sorry for recommending that...
 
Ares Xena
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslav Lehotsky wrote:Actually, for second scenario it could be even better, by not using copy of the original list at all, and just append by addAll to the originalList same originalList, eg: originalList.addAll(originalList).


Hi! Thanks for the replies. From what I understand scenario 1 is more likely. Your approach worked in my IDE. Probably made it more complicated in my head than it actually was. Unfortunately, the challenge doesn't accept the code I wrote.

This is what I wrote based on your original comment:



For some unknown reason, it outputs as   a, b, c:

Failed. Wrong answer

This is a sample test from the problem statement!

Test input:
ListMultiplicator class

Correct output:
Well done!

Your code output:
[a, b, c, a, b, c]
Assertion failed: Multiplication error



Scenario 2 didn't seem to work. If I replace with   it says there is an incompatible type issue. Either way scenario 1 that you wrote worked for me. So thanks, really appreciate it!


 
Miroslav Lehotsky
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

...This is what I wrote based on your original comment...



The code there was just simplified pseudocode. You just copied reference to the same list... You need to make really a separate list object (eg. List<?> listCopy = new ArrayList<>(list);) And regarding second scenario, see post above, it's not safe operation performed like that, it can work for you, but it's undefined behavior when adding list to itself... So in that case you should go with the copies as well...
 
Ares Xena
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslav Lehotsky wrote:

...This is what I wrote based on your original comment...



The code there was just simplified pseudocode. You just copied reference to the same list... You need to make really a separate list object (eg. List<?> listCopy = new ArrayList<>(list);) And regarding second scenario, see post above, it's not safe operation performed like that, it can work for you, but it's undefined behavior when adding list to itself... So in that case you should go with the copies as well...


Awesome, cool. Thanks for clarifying!
 
Saloon Keeper
Posts: 6921
65
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ares Xena wrote:From what I gather from the hints tab, you can use a helper method to store the original array. However, I'm just completely lost on writing the logic for this challenge after about an hour. If anyone could be of use to explain how to solve it, that'd be great!


What have you tried so far? Can you post it even if it doesn't work.
 
Carey Brown
Saloon Keeper
Posts: 6921
65
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Seems that you are dealing with the behavior of three different cases:
n == 0, clear the list
n == 1, leave the list alone
n > 1, append n-1 copies of the original list
 
Campbell Ritchie
Marshal
Posts: 67939
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Append n copies to a new List and substitute the new List. Isn't there an n copies method in Collections? Does that only apply to n copies of one object?

[addition}Yes. See this link. That won't help, unless you use flatMap() or similar.
 
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought the original problem was pretty clear on one point:

The original list content should be changed after method returns.



Based on that, why would we ever talk about making a new list?  Note also that the method provided has a void return, so there's no way to return a new list anyway.  You can only modify the original list, as requested.  They also haven't asked for anything to be printed, have they?  That's useful for debugging, but it's not what they're asking for.

Aside from that issue, Ares, I suggest testing your code to make sure it gives appropriate responses for n-0, n=1, and n=2.
 
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Something you might want to think about: A List<?> cannot be added to.
 
Carey Brown
Saloon Keeper
Posts: 6921
65
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Append n copies to a new List and substitute the new List. Isn't there an n copies method in Collections? Does that only apply to n copies of one object?

[addition}Yes. See this link. That won't help, unless you use flatMap() or similar.


Because the method only has a local copy of the list reference variable, if you assign to it (ie "substitute" it) you are not changing the list that was passed in. If you create a new list you'd have to copy the contents back to the original list.
 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Has anyone tried to implement their suggestions? Because again, you're going to run into the fact that List<?> cannot normally be added to. You have to get around that first before anything else.
 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hint: you don't have to put all your solution in that one method. You can create other methods, too.
 
Mike Simmons
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I see two ways to solve that problem, and Ares has already found one of them:


It's a mistake to call this a copy.  But, the line does serve the useful function of converting to a raw type and disabling the generic type checking, which in this case just gets in the way.

The other, perhaps more elegant way, would be to figure out what the method signature should have been for this problem, write a method with that signature, and simply forward the call from one method to another...
 
Miroslav Lehotsky
Ranch Hand
Posts: 82
1
VI Editor Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another solution I see is introduce new method with type parameter, in essence its the same as without using generics at all, but at least compiler won't cry about this



It's actually what Mike Simmons proposed above...
 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Mike Simmons wrote:But, the line does serve the useful function of converting to a raw type and disabling the generic type checking, which in this case just gets in the way.


Since the list references itself, it will only behave correctly when n == 2. Any n greater than 2, the code will give incorrect results.
 
Mike Simmons
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's why I didn't quote the rest of the code, because it doesn't work correctly as written.  But the line I quoted does allow you to be able to add things to the list, effectively disabling the generic type.  Not that I recommend this approach in general, but it can be done.
 
Bartender
Posts: 3747
154
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Late to the discussion, and sorry if my remark has already been remarked.

The exercise says "without changing the signature". So I made this method:

and then changing the argument list in the code that invokes this method. Easy peasy.
 
Mike Simmons
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, the code doesn't work for n=2 either.
 
Mike Simmons
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:Late to the discussion, and sorry if my remark has already been remarked.

The exercise says "without changing the signature". So I made this method:

and then changing the argument list in the code that invokes this method. Easy peasy.


Ummm... OK.  I understand that the return type is not part of the signature, as defined in the JLS.  (Though oddly, it is part of the signature as defined in the JVM spec.) But, does your code still modify the original list, as specified?  If so, how?  Perhaps using one of the other tricks already discussed?  In which case, what do you gain by changing the return type?
 
Piet Souris
Bartender
Posts: 3747
154
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Mike,

I can't answer this here, since that would spoil the exercise.
But a clue is this description:
The original list content should be changed after method returns.
 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
While there is certainly room for that kind of interpretation of the requirements, the answer was given already by Miroslav as suggested by Mike. I don't think there's any harm in you posting your solution, Piet, or at least the gist of it.
 
Piet Souris
Bartender
Posts: 3747
154
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Mike Simmons
Master Rancher
Posts: 3437
35
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmmm, OK you have a very different interpretation of "should be changed after method returns", but all right.  You're also still using a raw type to disable the generic type, resulting in warnings, much like Ares' earlier trick.  Your code does have the advantage of working correctly for all values of n... but it's also possible to do that with the original method declaration, modifying the original list in place, without, ummm, deliberately reinterpreting the requirements. ;)
 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Mike Simmons wrote:The other, perhaps more elegant way, would be to figure out what the method signature should have been for this problem, write a method with that signature, and simply forward the call from one method to another...


 
Campbell Ritchie
Marshal
Posts: 67939
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslav Lehotsky wrote:. . . it's just pseudocode . . .

Afraid you didn't make that clear.

Sorry  . . .

Apology accepted `
 
"How many licks ..." - I think all of this dog's research starts with these words. Tasty tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!