Language Tricks to Shorten My Java Code? [closed] - java

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
I am currently rediscovering Java (working with Ruby a lot recently), and I love the compilation-time checking of everything. It makes refactoring so easy. However, I miss playing fast-and-loose with types to do an each loop. This is my worst code.
Is this as short as it can be? I have a collection called looperTracks, which has instances that implement Looper. I don't want to modify that collection, but I want to iterate through its members PLUS the this (which also implements Looper).
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks.length + 1);
for (LooperTrack track : looperTracks) {
allLoopers.add(track);
}
allLoopers.add(this);
for (Looper looper : allLoopers) {
// Finally! I have a looper
I'm particularly concerned about any features that are new to Java from 1.5 on that I may have missed. For this question I am not asking about JRuby nor Groovy, though I know that they would work for this.
Edit: Sorry (too much Ruby!)... looperTracks is of type LooperTrack[] and LooperTrack implements Looper.

You could at least use the fact that you can construct one collection using another as the base values. According to the docs:
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator. The ArrayList instance has an initial capacity of 110% the size of the specified collection.
Which means that there is probably going to be room forthis without having to do any resizing.
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
for (Looper looper : allLoopers) {
// Finally! I have a looper

There are at least two possible built-in ways to shorten your code:
You could use Collection.addAll(Collection) that appends each element in the collection passed as parameter to the end of the collection.:
List<Looper> allLoopers = new ArrayList<Looper>();
...
allLoopers.addAll(looperTracks);
allLoopers.add(this);
for(Looper looper : allLoopers) {
...
}
or you can use a constructor that takes a collection as a parameter:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
Due to the change of question: All arrays can easily be converted to collections using java.util.Arrays e.g.
List<Looper> someLooperTracks = Arrays.asList(looperTracks).
This will wrap the array in a fixed-size list.

I don't think you can make it shorter than this...
for (Looper looper : new ArrayList<Looper>(looperTracks){{ add(EnclosingClass.this); }}) {
// Finally! I have all loopers
}

Guava makes this pretty easy:
for (Looper looper : ObjectArrays.concat(looperTracks, this)) {}
Here is the documentation for the method ObjectArrays#concat.

I've just implemented an Iterator of Iterables (it is implemented in a more robust/tested/reviewed way by Guava Iterables.concat(Iterable...)):
// make a concatenation of iterables
public static <T> Iterable<T> $(final Iterable<T> first, final Iterable<T>... iterables) {
List<Iterator<T>> allIterables = new LinkedList<Iterator<T>>();
allIterables.add(first.iterator());
for (Iterable<T> iterable : iterables) {
allIterables.add(iterable.iterator());
}
final Iterator<Iterator<T>> iterators = allIterables.iterator();
return new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Iterator<T> current = iterators.next();
#Override
public boolean hasNext() {
if (current.hasNext()) {
return true;
} else {
if (iterators.hasNext()) {
current = iterators.next();
return current.hasNext();
} else {
return false;
}
}
}
#Override
public T next() {
return current.next();
}
#Override
public void remove() {
}
};
}
};
}
using it your code becomes:
for (Looper looper : $($(looperTracks), this)) {
}
in the case you care the implementation is being part of my Dollar library (relesead as LGPL3).

Why can't you just add them all as part of the constructor call?
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
for(Looper looper : allLoopers) {
...
}

Depending on typing, you could use:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
or:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks.length + 1);
allLoopers.addAll(looperTracks);
allLoopers.add(this);

In case you don't want to use Groovy or JRuby because of their dynamic nature, you should consider using Scala. Scala is statically typed but more concise than Java.

Is it a requirement that you assemble everything into one list? If not, what's wrong with this?
for (Looper looper : looperTracks) {
doSomething(looper);
}
doSomething(this);

Try
Looper[] loop = new Looper[looperTracks.length + 1];
System.arraycopy(looperTracks, 0, loop, 0, looperTracks.length);
loop[looperTracks.length] = this;
for (Looper l : loop) { ... }
but honestly, why not just loop through the existing array, and then do whatever you want to do with the loop to this afterwards?
The List-version of the above looks like:
List<Looper> loop = new ArrayList<Looper>(Arrays.asList(looperTracks));
loop.add(this);
for (Looper l : loop) { ... }

You can try using an immutable list by using the nCopies() method. Quoting from the API reference,
public static <T> List<T> nCopies(int n, T o)
Returns an immutable list consisting
of n copies of the specified object.
The newly allocated data object is
tiny (it contains a single reference
to the data object). This method is
useful in combination with the
List.addAll method to grow lists. The
returned list is serializable.
this will avoid the first foreach iteration.

I'm just going to throw this out there but don't try and make your code shorter at the expense of making it readable.
Readable code is always my aim when I start writing code, simply because I know that at some point in the future either myself or someone else is going to look at it and have to understand it.

Related

How to tell java's TreeSet or HashMap that the order by which its contenst are indexed is the insertion order(don't want LinkedHashMap)?

Eg; I want my TreeSet / HashMap to store 1,19,3,4,2,0 in that order since it is the order they are added to the map.
I hear that LinkedHashMap is the go-to solution. But my question is, can we produce the same result with TreeSet/HashMap, with some modification introduced to comparedTo()?
No. You cannot do that. You must use LinkedHashMap or another custom map implementation; TreeMap and HashMap cannot support insertion order.
You could do it with a very very complicated compareTo(...) method, but it would involve basically keeping track of the state of the tree yourself, manually, somewhere external to the tree. That's just re-creating a LinkedHashMap without using a LinkedHashMap. Same thing, but much more complex and hard to read and maintain code. No reason to do that.
"You cannot do that." Well, you can. All you need to do is add the insertion order to the object you're storing and account for it in the compareTo or comparator.
#Override
public int compareTo(Object o) {
int returnValue = 0;
if(o instanceof InsertionObject) {
InsertionObject newObject = (InsertionObject)o;
if(this.insertionOrder != newObject.insertionOrder) {
if(this.insertionOrder < newObject.insertionOrder) {
returnValue = -1;
}
else {
returnValue = 1;
}
}
}
else {
throw new RuntimeException("Insert error message here.");
}
return returnValue;
}
I'm not saying you should, but you could. This smells like an interview question or a homework problem, so they probably are just testing to see if the poster understands what is going on inside the underlying collections?

thread-safe CopyOnWriteArrayList reverse iteration

Consider the following code snippet:
private List<Listener<E>> listenerList = new CopyOnWriteArrayList<Listener<E>>();
public void addListener(Listener<E> listener) {
if (listener != null) {
listenerList.add(listener);
}
}
public void removeListener(Listener<E> listener) {
if (listener != null) {
listenerList.remove(listener);
}
}
protected final void fireChangedForward(Event<E> event) {
for (Listener<E> listener : listenerList) {
listener.changed(event);
}
}
protected final void fireChangedReversed(Event<E> event) {
final ListIterator<Listener<E>> li = listenerList.listIterator(listenerList.size());
while (li.hasPrevious()) {
li.previous().changed(event);
}
}
There is a listener list that can be modified and iterated.
I think the forward iteration (see method #fireChangedForward)
should be safe.
The question is: is the reverse iteration (see method #fireChangedReversed) also safe in a multi-threaded environment?
I doubt that, because there are two calls involved: #size and #listIterator.
If it's not thread-safe, what is the most efficient way to implement #fireChangedReversed under the following circumstances:
optimize for traversal
avoid usage of locking if possible
avoid usage of javax.swing.event.EventListenerList
prefer solution without usage of third-party lib, e.g. implementation in own code possible
Indeed, listenerList.listIterator(listenerList.size()) is not thread-safe, for exactly the reason you suggested: the list could change size between the calls to size() and listIterator(), resulting in either the omission of an element from the iteration, or IndexOutOfBoundsException being thrown.
The best way to deal with this is to clone the CopyOnWriteArrayList before getting the iterator:
CopyOnWriteArrayList<Listener<E>> listenerList = ... ;
#SuppressWarnings("unchecked")
List<Listener<E>> copy = (List<Listener<E>>)listenerList.clone();
ListIterator<Listener<E>> li = copy.listIterator(copy.size());
The clone makes a shallow copy of the list. In particular, the clone shares the internal array with the original. This isn't entirely obvious from the specification, which says merely
Returns a shallow copy of this list. (The elements themselves are not copied.)
(When I read this, I thought "Of course the elements aren't copied; this is a shallow copy!" What this really means is that neither the elements nor the array that contains them are copied.)
This is fairly inconvenient, including the lack of a covariant override of clone(), requiring an unchecked cast.
Some potential enhancements are discussed in JDK-6821196 and JDK-8149509. The former bug also links to a discussion of this issue on the concurrency-interest mailing list.
One simple way to do that is to call #toArray method and iterate over the array in reverse order.
You could always just get a ListIterator and "fast-forward" to the end of the list as such:
final ListIterator<Listener<E>> li = listenerList.listIterator();
if (li.hasNext()) {
do{
li.next();
} while (li.hasNext());
}
while (li.hasPrevious()) {
li.previous().changed(event);
}
EDIT I switched the quirky exception-handling of my previous answer for a do/while loop that places the cursor of the ListIterator after the last element, in order to be ready for the next previous call.
RE-EDIT As pointed out by #MikeFHay, a do/while loop on an iterator will throw a NoSuchElementException on an empty list. To prevent this from happening, I wrapped the do/while loop with if (li.hasNext()).

Java: Return in a for loop

Is there a way to return some value from within a for loop without jumping out of the loop?
I am implementing a static analysis tool where I have to analyze a list of methods (CFGs) in a for loop. The size of CFG list is not known in advance. Each method in the for loop has to return some value. As asked above, is there a way to do it in a loop without breaking the loop? One possible alternative comes in mind is that I can unroll the loop, assuming the maximum list size could be some fixed value. But this does not solve the problem completely. Any help would be appreciated.
code looks like below.
for(CFG cfg: cfgList)
{
val = analyze(cfg);
return val; //I want for loop not to stop here.
}
P.S. I cannot store the values in a list to return values later.
Edit1:
For example, consider following statements.
call method1();
st2;
st3;
...
This method1() can be any of five different methods. For all five possible options, I want to analyze each of them, return their values and analyze rest of the statements accordingly. So, I would analyze these 5 methods as below.
call method1-option1();
st2;
st3;
...
call method1-option2();
st2;
st3;
...
call method1-option3();
st2;
st3;
...
Hope, it helps in understanding the question.
No you can not return value from loop without jumping out of it. According to your need you have to save value in other list and you can return that list after finishing the loop.
In Java 8, you can do:
Iterator<AnalysisResult> lazyAnalysisResults = cfgList.stream()
.map(cfg -> analyze(cfg))
.iterator();
And then the Iterator will supply new analyzed results one at a time, without you needing to collect them all into a list first.
Prior to Java 8, if you want your transformation to be lazy, the best you can do is to implement an Iterator yourself:
public final class AnalyzingIterator extends Iterator<AnalysisResult> {
private final Iterator<CFG> iter;
public AnalyzingIterator(Iterator<CFG> iter) {
this.iter = iter;
}
#Override public boolean hasNext() {
return iter.hasNext();
}
#Override public AnalysisResult next() {
return analyze(iter.next());
}
#Override public boolean remove() {
throw new UnsupportedOperationException();
}
}
If you don't want to store results in a List and return it all together you can use callback mechanism.
Use analyze() to start a new thread passing cfg as well as reference to this. When processing is over make that processing thread call a callback method on your current instance / thread passing the analyzed value. Continue to do whatever you intend to do with this returned value in the callback method. And you don't have to alter your for loop.

Updating a PriorityQueue when iterating it

I need to update some fixed-priority elements in a PriorityQueue based on their ID. I think it's quite a common scenario, here's an example snippet (Android 2.2):
for (Entry e : mEntries) {
if (e.getId().equals(someId)) {
e.setData(newData);
}
}
I've then made Entry "immutable" (no setter methods) so that a new Entry instance is created and returned by setData(). I modified my method into this:
for (Entry e : mEntries) {
if (e.getId().equals(someId)) {
Entry newEntry = e.setData(newData);
mEntries.remove(e);
mEntries.add(newEntry);
}
}
The code seems to work fine, but someone pointed out that modifying a queue while iterating over it is a bad idea: it may throw a ConcurrentModificationException and I'd need to add the elements I want to remove to an ArrayList and remove it later. He didn't explain why, and it looks quite an overhead to me, but I couldn't find any specific explanation on internet.
(This post is similar, but there priorities can change, which is not my case)
Can anyone clarify what's wrong with my code, how should I change it and - most of all - why?
Thanks,
Rippel
PS: Some implementation details...
PriorityQueue<Entry> mEntries = new PriorityQueue<Entry>(1, Entry.EntryComparator());
with:
public static class EntryComparator implements Comparator<Entry> {
public int compare(Entry my, Entry their) {
if (my.mPriority < their.mPriority) {
return 1;
}
else if (my.mPriority > their.mPriority) {
return -1;
}
return 0;
}
}
This code is in the Java 6 implementation of PriorityQueue:
private class Itr implements Iterator<E> {
/**
* The modCount value that the iterator believes that the backing
* Queue should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
private int expectedModCount = modCount;
public E next() {
if(expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
}
}
Now, why is this code here? If you look at the Javadoc for ConcurrentModificationException you will find that the behaviour of an iterator is undefined if modification occurs to the underlying collection before iteration completes. As such, many of the collections implement this modCount mechanism.
To fix your code
You need to ensure that you don't modify the code mid-loop. If your code is single threaded (as it appears to be) then you can simply do as your coworker suggested and copy it into a list for later inclusion. Also, the use of the Iterator.remove() method is documented to prevent ConcurrentModificationExceptions. An example:
List<Entry> toAdd = new ArrayList<Entry>();
Iterator it = mEntries.iterator();
while(it.hasNext()) {
Entry e = it.next();
if(e.getId().equals(someId)) {
Entry newEntry = e.setData(newData);
it.remove();
toAdd.add(newEntry);
}
}
mEntries.addAll(toAdd);
The Javadoc for PriorityQueue says explicitly:
"Note that this implementation is not synchronized. Multiple threads should not access a PriorityQueue instance concurrently if any of the threads modifies the list structurally. Instead, use the thread-safe PriorityBlockingQueue class."
This seems to be your case.
What's wrong in your code was already explained -- implementing iterator, which can consistently iterate through collection with intersected modification is rather hard task to do. You need to specify how to deal with removed items (will it be seen through iterator?), added items, modified items... Even if you can do it consistently it will be rather complex and unefficient implementation -- and, mostly, not very usefull, since use case "iterate without modifications" is much more common. So, java architects choose to deny modification while iterate, and most collections from Java collection API follow this, and throw ConcurrentModificationException if such modification detected.
As for your code -- for me, your just should not make items immutable. Immutability is great thing, but it should not be overused. If Entry object you use here is some kind of domain object, and you really want them to be immutable -- you can just create some kind of temporary data holder (MutableEntry) object, use it inside your algorithm, and copy data to Entry before return. From my point of view it will be best solution.
a slightly better implementation is
List<Entry> toAdd = new ArrayList<Entry>();
for (Iterator<Entry> it= mEntries.iterator();it.hasNext();) {
Entry e = it.next();
if (e.getId().equals(someId)) {
Entry newEntry = e.setData(newData);
it.remove();
toAdd.add(newEntry);
}
}
mEntries.addAll(toAdd);
this uses the remove of the iterator and a bulk add afterwards

Removing the "first" object from a Set

Under certain situations, I need to evict the oldest element in a Java Set. The set is implemented using a LinkedHashSet, which makes this simple: just get rid of the first element returned by the set's iterator:
Set<Foo> mySet = new LinkedHashSet<Foo>();
// do stuff...
if (mySet.size() >= MAX_SET_SIZE)
{
Iterator<Foo> iter = mySet.iterator();
iter.next();
iter.remove();
}
This is ugly: 3 lines to do something I could do with 1 line if I was using a SortedSet (for other reasons, a SortedSet is not an option here):
if (/*stuff*/)
{
mySet.remove(mySet.first());
}
So is there a cleaner way of doing this, without:
changing the Set implementation, or
writing a static utility method?
Any solutions leveraging Guava are fine.
I am fully aware that sets do not have inherent ordering. I'm asking about removing the first entry as defined by iteration order.
LinkedHashSet is a wrapper for LinkedHashMap which supports a simple "remove oldest" policy. To use it as a Set you can do
Set<String> set = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>(){
protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) {
return size() > MAX_ENTRIES;
}
});
if (!mySet.isEmpty())
mySet.remove(mySet.iterator().next());
seems to be less than 3 lines.
You have to synchronize around it of course if your set is shared by multiple threads.
If you really need to do this at several places in your code, just write a static method.
The other solutions proposed are often slower since they imply calling the Set.remove(Object) method instead of the Iterator.remove() method.
#Nullable
public static <T> T removeFirst(Collection<? extends T> c) {
Iterator<? extends T> it = c.iterator();
if (!it.hasNext()) { return null; }
T removed = it.next();
it.remove();
return removed;
}
With guava:
if (!set.isEmpty() && set.size() >= MAX_SET_SIZE) {
set.remove(Iterables.get(set, 0));
}
I will also suggest an alternative approach. Yes, it it changing the implementation, but not drastically: extend LinkedHashSet and have that condition in the add method:
public LimitedLinkedHashSet<E> extends LinkedHashSet<E> {
public void add(E element) {
super.add(element);
// your 5-line logic from above or my solution with guava
}
}
It's still 5 line, but it is invisible to the code that's using it. And since this is actually a specific behaviour of the set, it is logical to have it within the set.
I think the way you're doing it is fine. Is this something you do often enough to be worth finding a shorter way? You could do basically the same thing with Guava like this:
Iterables.removeIf(Iterables.limit(mySet, 1), Predicates.alwaysTrue());
That adds the small overhead of wrapping the set and its iterator for limiting and then calling the alwaysTrue() predicate once... doesn't seem especially worth it to me though.
Edit: To put what I said in a comment in an answer, you could create a SetMultimap that automatically restricts the number of values it can have per key like this:
SetMultimap<K, V> multimap = Multimaps.newSetMultimap(map,
new Supplier<Set<V>>() {
public Set<V> get() {
return Sets.newSetFromMap(new LinkedHashMap<V, Boolean>() {
#Override protected boolean removeEldestEntry(Entry<K, V> eldestEntry) {
return size() > MAX_SIZE;
}
});
}
});
Quick and dirty one-line solution: mySet.remove(mySet.toArray(new Foo[mySet.size()])[0]) ;)
However, I'd still go for the iterator solution, since this would be more readable and should also be faster.
Edit: I'd go for Mike Samuel's solution. :)

Categories