ArrayList constructor undefined when using nCopes(int, generic) - java

I have the following class:
class Node<T extends Comparable<T>> {
and this is the constructor am using:
Node(T data, int h) {
this.tower = new ArrayList<Node<T>>(Collections.nCopies(h, data));
this.data = data;
}
Why is it giving me the following error:
The constructor ArrayList<Node<T>>(Collections.nCopies(h, data)) is undefined

You are building an ArrayList that is meant to contain Node<T> but you are supplying to the constructor a List<T> (and not List<Node<T>>), you probably want
Node(T data, int h) {
this.tower = new ArrayList<Node<T>>(Collections.nCopies(h, new Node<T>(data)));
this.data = data;
}

Collections.nCopies is probably not what you want, as it will not actually create copies of the object itself, but only of the reference to it. Which means, changing the value of one of these nodes changes all, which is likely not what you want. If it isn't, then here's your solution:
Node(T data, int h) {
this.tower =
IntStream.range(0, h) // these two lines do
.mapToObj((ignore)->data) // what Collections.nCopies does
.map(Node::new) // but here we're creating unique objects
.collect(Collectors.toList());
this.data = data;
}
This way, each node is a separate object, but they all have the same initial value.

Related

Java variable substitution when it is reflected, and not

Like the code shows, as variable x is substituted to list, when the new instance of ListNode is substituted to x.next, it is reflected on both x and list(refer to the comment 1). I think this is because x refers to list.
However, when the new instance is substituted to x, it is reflected on only x, not list(refer to the comment 2).
Could you explain why this happens?
public class Sample {
public static void main(final String[] args) {
final ListNode list = new ListNode(0, null);
ListNode x = list;
//1.ListNode new instance is substituted for both x and list as x refers to list
x.next = new ListNode(1, null);
//2.ListNode new instance is substituted only for x, not list
x = new ListNode(1, null);
}
}
class ListNode {
int data;
ListNode next;
ListNode(final int data, final ListNode next) {
this.data = data;
this.next = next;
}
}
https://github.com/indrabasak/Books/blob/master/Head%20First%20Java%2C%202nd%20Edition.pdf
Read chapter 3 "Primitives and references" from this book. Your life will become much easier.
Unlike other languages like C++, most Java variables (except primitives) are references to Objects. So, after:
ListNode x = list;
both x and list reference the same object (x == list). Any modification you'll do (like changing the x.next field) will apply to both variables.
However, you can always change the object x is referencing (but not list, since it is final) and you do it with:
x = new ListNode(1, null);
After that x != list.
You can test with a primitive type (like int) to see what changes.

Why is there no difference in output for the below code?

I am pretty new to java and getting confused with the below code:
public class NewNode {
NewNode next = null;
int data;
public NewNode(int data) {
this.data = data;
}
public void addToNode(int data){
NewNode n = this;
System.out.println(n);
NewNode newlyCreated = new NewNode(data);
}
}
but even after changing the addToNode method as below:
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data);
NewNode n = this;
System.out.println(n);
}
The output of n doesn't change . If,this keyword refers to the current instance of the object then shouldn't newlyCreatedNode be the output in the second scenario.Please help....
According to the doc tutorials:
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called.
So in both example this refers to the object you call addToNode() on. The fact that you create an object within the method is irrelevant. So:
public void addToNode(int data){
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
NewNode newlyCreated = new NewNode(data); //Creates a random object
}
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data); //Creates a random object
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
}
this is the current instance i.e. the instance that invokes the addNode method.
Thus when you create a new Node by NewNode newlyCreated = new NewNode(data); it just creates a new Node locally. The current instance(i.e. this) remains the same.
Your output will change if you do this.data = data i.e. changing the data field of current instance
EDIT: Also you need to override the toString method to print NewNode otherwise it'll print default Object's toString method
Okay, take a look at this piece of code. Let me try to give you a simpler example.
Assume that we have a class like this:
class A {
int data;
void printData() {
System.out.println(this.data);
}
}
And then you create two instances of A like this:
A a1 = new A(); a1.data = 10;
A a2 = new A(); a2.data = 12;
So there are now two objects a1 and a2 which are of the A type.
Now let's call the printData() method on them. How would you do it?
a1.printData();
a2.printData();
Now look at the first print call, it is happening on the a1 object. So now control goes into the printData method, where the this will resolve to a1, so this.data will be same as a1.data from outside.
Now in the second call, yes you get it right. It is being invoked on a2 object, so inside the method printData, a2 will be assigned to this.
This is what it means when they say that this resolves to the current object.
Got it now?

Cascading Generic Type declarations in Java

I am having a hard time finding this anywhere if this is a common problem but I am dealing with what is essentially a cascading type problem.
public class Graph<E> {
private LinkedList<Node<E>> nodes;
public Graph() {
this.nodes = new LinkedList<>();
}
public E[] getNodes() {
ArrayList<E> list = new ArrayList<>();
for (Node<E> node : nodes)
list.add(node.getObject());
return list.toArray(new E[0]); // any way to make this line work?
}
// other important stuff
}
I want to do something like this, however I can't instantiate the generic array this way. Where the getNodes() returns the content of the Nodes, not the Nodes themselves, but I can't figure out how.
I was thinking that the Node generic being defined by the Graph generic would mean that the Node class always has the same type as the Graph class. Is that not the case?
The Node class looks like
public class Node<E> {
private LinkedList<Edge> edges;
private E obj;
public E getObject() {
return obj;
}
// other useful stuff
}
Thanks for any help!
EDIT: all that is needed now is to make the returned Array of the right type. Is there a way to get an Array from an ArrayList that has a generic type assignment?
You need some form of reification of E in your getThings method.
If you want to keep the signature of getThings as it is, you can add a construtor parameter to provide the actual class E. With that class you can create an array to pass to the toArray(E[]) method of List<E>
private final Class<E> type;
private final List<E> list;
public CustomClass(Class<E> type) {
this.type = type;
this.list = new ArrayList<>();
}
#SuppressWarnings("unchecked")
public E[] getThings() {
Object[] reference = (Object[]) Array.newInstance(type, list.size());
return (E[]) list.toArray(reference);
}
Someone else came up with an answer that did not work but gave me an idea that ended up working, but they also put it in the comments section of the question so I will reiterate here and answer my own question.
This code works to solve the problem. I more or less lifted the logic from the ArrayList source code for their toArray(E[] a) function (with some of the meat of it cut out of course).
#SuppressWarnings("unchecked")
public E[] getNodes(E[] a) {
int size = nodes.size();
// creates an empty array of the right size and type
E[] arr =(E[]) java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
// fills that array with the correct data
for (int i = 0; i < size; i++)
arr[i] = nodes.get(i).getObject();
return arr;
}
Look at the ArrayList source code in order to see some logic that goes a step farther and accomplishes the same task in a way that is also Thread safe.

Generic array in java issue

I have this bit of code and it keeps saying that it cannot create a generic array, but, I don't have a generic in my Node class, just an Object field. The Node class is an inner class. Why is it doing this?
public class TernarySearchTrie<E> implements TrieInterface<E> {
private Node[] root = new Node[256];
private int size = 0;
private class Node {
char c;
Node left, mid, right;
Object value;
}
}
Add the static modifier to Node class:
private static class Node {
char c;
Node left, mid, right;
Object value;
}
Without static, it depends of the TernarySearchTrie class, that have generics.
What you do in the problematic new Node[256] is actually TernarySeachTrie<E>.Node[256]. One solution is to use raw type:
Node[] root = TernarySearchTrie.Node[256];
Of course the compiler gives you a warning for this.

Casting a string to an object

when I create an object of the class BinaryTreeNode , I want to pass two String in the Constructor rather than an object of the class BinaryTreeNode how can I do that.
BinaryTreeNode(BinaryTreeNode left,BinaryTreeNode right) {
this.left = left;
this.right = right;
}
BinaryTreeNode b = new BinaryTreeNode("B","A");
Write another constructor that takes two String parameters.
BinaryTreeNode(String left, String right) {
//whose knows why I want to do this...
}
You can't cast a String into a BinaryTreeNode, that would throw an Exception.
It is not possible to cast any object to a type which it is not.
But that is fine, and I suspect it is not the root of the problem, because it doesn't make sense to treat a String object as a BinaryTreeNode - they have naught in common except that which they both inherit from Object.
Thus, I would either make the "node/leaf value" part of the BinaryTreeNode type or, I may introduce a leaf node type such as:
class BinaryTreeLeafNode extends BinaryTreeNode {
public final String value;
public BinaryTreeLeafNode (String value) {
super(null, null); // got anything better? :|
this.value = value;
}
}
Then:
tree = new BinaryTreeNode(
new BinaryTreeLeafNode("Left"),
new BinaryTreeLeafNode("Right"));
And perhaps if I wanted to hide the details, then an overload could be introduced:
public BinaryTreeNode (String leftValue, String rightValue) {
this(new BinaryTreeLeafNode(leftValue), new BinaryTreeLeafNode(rightValue));
}
(I would advise against widening the left/right member and constructor types to to Object, as that will eliminate a good bit of type-safety.)

Categories