Should we localize scope variables at cost of multiple declarations - java

Effective java greatly stresses on localizing scope of variable. But in case we have an if else it may cause multiple declations eg:
public List<E> midPoint() {
if (first == null) {
throw new NullPointerException("Linked list is empty");
}
if (first.next == null) {
ArrayList<E> arr = new ArrayList<E>();
arr.add(first.element);
return arr;
}
Node<E> fast = first.next;
Node<E> slow = first;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// even count for number of nodes in linkedlist.
if (fast != null) {
ArrayList<E> arr = new ArrayList<E>();
arr.add(slow.element);
arr.add(slow.next.element);
return arr;
} else {
ArrayList<E> arr = new ArrayList<E>();
arr.add(slow.element);
return arr;
}
}
In the above code Arraylist defination / declaration occurs multiple times, but the variable is localized.. Is it good the way it is OR should arrayList be declared at the top and returned where its matches condition : eg:
public List<E> midPoint() {
if (first == null) {
throw new NullPointerException("Linked list is empty");
}
ArrayList<E> arr = new ArrayList<E>(); // NOTE - JUST A SINGLE DECLARATION.
if (first.next == null) {
arr.add(first.element);
return arr;
}
Node<E> fast = first.next;
Node<E> slow = first;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// even count for number of nodes in linkedlist.
if (fast != null) {
arr.add(slow.element);
arr.add(slow.next.element);
return arr;
} else {
arr.add(slow.element);
return arr;
}
}
Thanks

In this case, it is advised that you declare it in only one place. It will be more readable and spare some lines of code.
Renaming would also be good, maybe something that suggests that is the final result of your method (like returnArray, resultArray).
In other circumstances, when that list would mean several different things, it would be really better to declare it, in that case, you would have different names too.

Should we localize scope variables at cost of multiple declarations
Different people (including well respected authors of well-known text books) will have different opinions on what makes code readable. The problem, is that readability is a subjective measure: it depends on the reader.
So I think it is up to you to decide. The chances are that you are going to be the primary reader of your code, at least to start with. So ...
Use the version that you think makes the code more readable.
If you want a second opinion, ask your co-workers.
If you have chosen to use a style guide ... be guided by what it says.
FWIW, my personal opinion is that it really depends on the context. Sometimes it is better to localize, sometimes not. A lot depends on how "far away" the declaration is from the usage, and how intuitive the meaning of the variable is. (For example, if arr was named res or result, you would not need to look at the variable declaration ... assuming you knew the signature of the current method.)

There's nothing wrong with declaring it multiple times, but you have a lot of repeated code: you can significantly improve your code by refactoring.
In your case, the JDK provides a convenience utility method to create ArrayLists in-line:
Instead of:
ArrayList<E> arr = new ArrayList<E>();
arr.add(slow.element);
arr.add(slow.next.element);
return arr;
Code this:
return Arrays.asList(slow.element, slow.next.element);
And so forth.
Note that the list returned from asList() is not modifiable. If you need a modifiable list, pass it to ArrayList's copy constructor:
return new ArrayList(Arrays.<E>asList(slow.element, slow.next.element));

Related

Why the HashMap#resize implementation is so complex?

After reading source code of java.util.HashMap#resize , I'm very confused with some part -- that is when some bin has more than one node.
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
Why I feel this part is no need to exist? Just use below code
newTab[e.hash & (newCap - 1)] = e;
is ok -- I think they have the same effect.
So why bother to have so many code in the else branch?
At resize, every bin is split into two separate bins. So if the bin contained several linked items, you cannot move all of them into the single target bin based on the hash of the first item: you should recheck all the hashes and distribute them into "hi" and "lo" bin, depending on the new significant bit inside the hash ((e.hash & oldCap) == 0). This was somewhat simpler in Java 7 before the introduction of tree-bins, but the older algorithm could change the order of the items which is not acceptable now.
EDIT:
The threshold for treefying a bin changes as the table is made bigger. That's what it is doing.
I haven't read the entire file, but this could be a possible reason (line 220)
The use and transitions among plain vs tree modes is
complicated by the existence of subclass LinkedHashMap. See
below for hook methods defined to be invoked upon insertion,
removal and access that allow LinkedHashMap internals to
otherwise remain independent of these mechanics. (This also
requires that a map instance be passed to some utility methods
that may create new nodes.)

could ConcurrentLinkedDeque clear be implemented as resetting head tail pointer?

/**
* Removes all of the elements from this deque.
*/
public void clear() {
while (pollFirst() != null)
;
}
current implementation is just pop the elements in the queue one by one, but could that be done by just resetting the head and tail pointer term to an empty queue ?
what's need to be taken care here?
The pollFirst() method does a lot more than just pop items from the queue. It does it in a thread-safe manner.
public E pollFirst() {
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && p.casItem(item, null)) {
unlink(p);
return item;
}
}
return null;
}
Since you want to keep your concurrent collection concurrent, one way is to make sure you're using already concurrent operations, such as pollFirst().
It's also worth noting that clear() is "less important" as an operation compared to others, so even though it might be possible to implement it differently, doing so would be of little use.

Create a C++ preorder iterator to supply tree nodes to a loop

I am trying to write a C++ program to supply tree nodes to this loop:
bin_tree<int> *my_tree = ...
for (bin_tree<int>::iterator n = my_tree->begin();
n != my_tree->end(); ++n)
{
cout << *n << "\n";
}
The class I have is written in Java, and I would like to translate it into C++, however I am having trouble doing so. This is the class:
class BinTree<T> implements Iterable<T> {
BinTree<T> left;
BinTree<T> right;
T val;
// other methods: insert, delete, lookup, ...
public Iterator<T> iterator()
{
return new TreeIterator(this);
}
private class TreeIterator implements Iterator<T>
{
private Stack<BinTree<T>> s = new Stack<BinTree<T>>();
TreeIterator(BinTree<T> n)
{
if (n.val != null) s.push(n);
}
public boolean hasNext()
{
return !s.empty();
}
public T next()
{
if (!hasNext()) throw new NoSuchElementException();
BinTree<T> n = s.pop();
if (n.right != null) s.push(n.right);
if (n.left != null) s.push(n.left);
return n.val;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
}
Any help on how to write this program correctly in C++ would be appreciated, I am not sure how to properly implement the preorder iterator.
If you are trying to create a container that supports iterators I would suggest the following (you probably know all this but it may help you write good C++):
Understand iterators (in your case it may make sense to have bidirectional iterators). Iterators are wrappers to pointers in C++.
Understand the underlying data structure you want (binary tree or binary search tree?).
How should an iterator traverse a tree? (Preorder,inorde,postorder, or level order)
My approach would be to write my own node class/struct. Then write an iterator class that handles the pointer manipulation. If you need to handle allocations a certain way I would write a custom allocator to help too. Finally write your container that uses the other classes. (Modular and separates out functionality in way that is easy to understand in C++)
If you are just looking for the iterator logic and have everything else you need; begin is the first address and can be wrapped as &data [0] for example. End is the last address in similar manner. ++ operator is supported on pointers and will move along linearly towards end. Still will want to figure out moving the tree should work! May even provide multiple ways.
Good luck!

Java : Merging two sorted linked lists

I have developed a code to merge two already sorted linked lists in java.
I need help with the following:
How do I retain the value of head node of merged list without using tempNode?
Can this code be better optimized?
public static ListNode mergeSortedListIteration(ListNode nodeA, ListNode nodeB) {
ListNode mergedNode ;
ListNode tempNode ;
if (nodeA == null) {
return nodeB;
}
if (nodeB == null) {
return nodeA;
}
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode = nodeA;
nodeA = nodeA.getNext();
}
else
{
mergedNode = nodeB;
nodeB = nodeB.getNext();
}
tempNode = mergedNode;
while (nodeA != null && nodeB != null)
{
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode.setNext(nodeA);
nodeA = nodeA.getNext();
}
else
{
mergedNode.setNext(nodeB);
nodeB = nodeB.getNext();
}
mergedNode = mergedNode.getNext();
}
if (nodeA != null)
{
mergedNode.setNext(nodeA);
}
if (nodeB != null)
{
mergedNode.setNext(nodeB);
}
return tempNode;
}
1: You have to keep a record of the first node, which means you will have to store it in a variable such as tempNode.
2: No. There's not much to optimize here. The process is quite trivial.
There are a few possibilities:
1) Instead of using mergedNode to keep track of the previous node, use nodeA.getNext().getValue() and nodeB.getNext().getValue(). Your algorithm will become more complex and you will have to deal with a few edge cases, but it is possible to eliminate one of your variables.
2) Use a doubly linked-list, and then use either nodeA.getPrev().getValue() and nodeB.getPrev().getValue() instead of mergedNode. You will also have to deal with edge cases here too.
In order to deal with edge cases, you will have to guarantee that your references can not possibly be null before calling getPrev(), getNext() or getValue(), or else you will throw an exception.
Note that the above modifications sacrifice execution time slightly and (more importantly) simplicity in order to eliminate a variable. Any gains would be marginal, and developer time is far more important than shaving a microsecond or two off of your operation.

Java Splitting integer Linked List

I need to write a method that starts with a single linked list of integers and a special value called the splitting value. The elements of the list are in no particular order. The method divides the nodes into two linked lists: one containing all the nodes that contain an element less than the splitting value and one that contains all the other nodes. If the original linked list had any repeated integers (i.e., any two or more nodes with the same element in them), then the new linked list that has this element should have the same number of nodes that repeat this element. The method returns two head references - one for each of the linked lists that were created.
I have been spent countless hours trying to get this right and think this is the closest but I have an error while compiling that my copyTail* IntNodes may not be initialized. I also may be completely wrong with my code....
Any help pointing in me in the right direction??
public static IntNode[ ] listSplitLessGreater(IntNode source, int splitter)
{
IntNode copyHeadLess;
IntNode copyTailLess;
IntNode copyHeadGreater;
IntNode copyTailGreater;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
if (splitter < source.data)
{
if (less)
{
copyHeadLess = new IntNode(source.data, null);
copyTailLess = copyHeadLess;
less=false;
}
else
{
source = source.link;
copyTailLess.addNodeAfter(source.data);
copyTailLess = copyTailLess.link;
}
}
else
{
if (greater)
{
copyHeadGreater = new IntNode(source.data, null);
copyTailGreater = copyHeadGreater;
greater=false;
}
else
{
source = source.link;
copyTailGreater.addNodeAfter(source.data);
copyTailGreater = copyTailGreater.link;
}
}
}
//Return Head References
answer[0] = copyHeadLess;
answer[1] = copyHeadGreater;
return answer;
}
I think you're making it more complicated than it needs to be, by modelling a list just with a single class (IntNode). If you model it as "the list" and "a node in the list" then it's easy to have an empty list. You also don't need to keep track of both the head and the tail - the list can do that. At that point, it's very simple:
Create two empty lists, one for "lower" and one for "not lower"
Iterate over the original list:
Work out which list to add the element to
Add the element
Return both lists (e.g. using an array as you have done)
Note that even without that, you can make your code simpler by just using null to mean "I haven't got this list yet". At the moment your code won't compile, as copyHeadLess etc aren't definitely assigned when they're used. You know that you won't try to use them until they've been assigned, but the compiler doesn't. I'd still recommend the remodelling approach though :)
If source isn't null, but source.link is null (list is only composed of one element) then you never assign to your copyHeadLess, etc, variables. Try initializing them to null or whatever the default is:
IntNode copyHeadLess = null;
IntNode copyTailLess = null;
IntNode copyHeadGreater = null;
IntNode copyTailGreater = null;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
// what about case where source isn't null but source.link is null?
}
//Return Head References
answer[0] = copyHeadLess; // this may have never been assigned in your original code
answer[1] = copyHeadGreater; // this may have never been assigned in your original code
return answer;
}

Categories