This week's book giveaway is in the Java 8 forum.
We're giving away four copies of Java 8 in Action and have Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft on-line!
See this thread for details.
The moose likes Java in General and the fly likes Combing String [] Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Combing String []" Watch "Combing String []" New topic
Author

Combing String []

Luke Shannon
Ranch Hand

Joined: Sep 30, 2004
Posts: 239


I would like to combine these 2 arrays into one array. Using a loop I can put it in this:

String[] returnSyns = new String[wordSyns.length + sentenceSyns.length];

But that is a little messy. Can anyone suggest a more clever way (clever as is less code to write)? There has to be a class somewhere that handles this. I'm currently looking through Apache Commons Lang with no luck so far.


Thanks,

Luke
[ March 11, 2005: Message edited by: Luke Shannon ]

Luke
SCJP
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
In my own humble opinion, (no, I won't degrade myself by writing IMHO), using easily-understood code, even if a bit messy, is waaay preferable to some super obscure method. I'd say you're best bet is to just create a new array of the appropriate size, and stick everything in its appropriate place.


I've heard it takes forever to grow a woman from the ground
Layne Lund
Ranch Hand

Joined: Dec 06, 2001
Posts: 3061
You could look at System.arraycopy(). This method copies one array into another at the specified position. See the JavaDocs for details.

Layne


Java API Documentation
The Java Tutorial
Alexandru Popescu
Ranch Hand

Joined: Jul 12, 2004
Posts: 995
Agree with you Nick, except when you don't reinvent the wheel and you already know the API (see Layne's suggestion ).

--
:alex |.::the_mindstorm::.


blog - InfoQ.com
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24168
    
  30

There's a couple of ways you could do it with the Collections API. In JDK 1.4 and before, I think the best you can do is something like

ArrayList list = new ArrayList();
list.addAll(Arrays.asList(wordSyns));
list.addAll(Arrays.asList(sentenceSyns));
String[] allSyns = (String[]) list.toArray(new String[list.size()]);

In JDK 1.5, it gets a little easier:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, wordSyns);
Collections.addAll(list, sentenceSyns);
String[] allSyns = list.toArray(new String[list.size()]);


[Jess in Action][AskingGoodQuestions]
Alexandru Popescu
Ranch Hand

Joined: Jul 12, 2004
Posts: 995
I am sorry I have to disagree with you Ernest, but for the above the best suited is still System.arrayCopy (less object creation, less code execution for redimensioning the lists).

--
:alex |.::the_mindstorm::.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
I have an ArrayUtils.concat at work. As far as I remember, it makes use of reflection to instanciate an array of the correct type and System.arraycopy to copy the content of the two arrays...


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24168
    
  30

Originally posted by Ali Pope:
for the above the best suited is still System.arrayCopy


He didn't ask for the most efficient possible code. He asked for clever code, which I interpreted to mean simple, easy to read, easy to get right the first time, easier code than the loop version.

Here's the arraycopy version, which is indeed the most performant:

String[] allSyns = new String[wordSyns.length + sentenceSyns.length];
System.arraycopy(wordSyns, 0, allSyns, 0, wordSyns.length);
System.arraycopy(sentenceSyns, 0, allSyns, wordSyns.length, sentenceSyns.length);

If you took 100 junior programmers and had them write the ArrayList version and the arraycopy version, how many do you suppose would get the ArrayList version right the first time? How many do you suppose would get the arraycopy() version right the first time?

Looking at my code, how long would it take to determine by inspection whether each version was written correctly? Given that each version compiles, could you tell whether it was correct without looking at the API docs?

Now suppose you have not only wordSyns and sentenceSyns, but need to add paragraphSyns as well. How many lines change in the ArrayList version? How many change in the arraycopy() version? Which change is easier to make?

Performance is only one consideration when writing code -- and it's not the most important one.
Alexandru Popescu
Ranch Hand

Joined: Jul 12, 2004
Posts: 995
Ouch ... that heart.


If you took 100 junior programmers and had them write the ArrayList version and the arraycopy version, how many do you suppose would get the ArrayList version right the first time? How many do you suppose would get the arraycopy() version right the first time?


They will probably go for the 1st solution with the iteration. That's why I thought at the 2nd step to suggest the right solution and not some other way to write it (the rewritten code is based finally on exactly System.arraycopy ;-) ).


Given that each version compiles, could you tell whether it was correct without looking at the API docs?


Defintely i can.


Now suppose you have not only wordSyns and sentenceSyns, but need to add paragraphSyns as well. How many lines change in the ArrayList version? How
many change in the arraycopy() version? Which change is easier to make?


Exactly same no of lines.


Performance is only one consideration when writing code -- and it's not the most important one.


I fully agree with this.

respectfully,
--
:alex |.::the_mindstorm::.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Ernest Friedman-Hill:
If you took 100 junior programmers and had them write the ArrayList version and the arraycopy version, how many do you suppose would get the ArrayList version right the first time? How many do you suppose would get the arraycopy() version right the first time?


I'm not sure that this is a good argument. Beginners often code more circumstantial solution than need be, because they don't know how to make it easier, or because the easier way required them to make use of concepts they aren't yet ready for. To me at least, your solution certainly doesn't look easier than the arraycopy solution.


Looking at my code, how long would it take to determine by inspection whether each version was written correctly? Given that each version compiles, could you tell whether it was correct without looking at the API docs?


Yes. I'd write unit tests for it. For both versions, that is. It's something I'd advice every beginner to do, too.


Now suppose you have not only wordSyns and sentenceSyns, but need to add paragraphSyns as well. How many lines change in the ArrayList version? How many change in the arraycopy() version? Which change is easier to make?


The best answer is, of course, to not duplicate the logic for the second concatenation. If you can write

concat = ArrayUtils.concat(ArrayUtils.concat(wordSyns, sentenceSyns), paragraphSyns);

it doesn't matters at all which approach you used.


Performance is only one consideration when writing code -- and it's not the most important one.


Full agreement, of course!

Still, I'd say to someone who is used to it and knows ways to assert that his actually solutions work, the arraycopy solution will look simpler. And I think it's valuable to learn those skills - especially since we are in the "intermediate" forum...
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24168
    
  30

Originally posted by Ali Pope:

Exactly same no of lines.


This proves my point about the difficulty of getting things right the first time! In either ArrayList version, you have to add exactly one line, and change none. In the arraycopy() version, you have to add a line to do an additional arraycopy(), and also change the first line that dimensions the big array. That's two changes; I'm betting you forgot the first one.

Now if you're doing TDD (which Ilja is recommending and which I believe he knows I'm a fervent adherent of!) your test fails with an ArrayIndexOutOfBoundsException, and you have to go back and make that second change, and re-run the test. If you got it right the first time, your test passes as soon as you write the code. If you multiply this by a few dozen times a day, you'll have slowed yourself down significantly by not getting things right the first time.

Finally, although you and I know the correct order of the arguments to arraycopy(), it's a very easy thing to get wrong. arraycopy() has what Steve Maguire calls a "Candy Machine Interface", with multiple like-typed inputs that can be exchanged to bad effect. I'm not saying that you should avoid arraycopy; I'm just saying that it's a tricky method that's best used in library code.

Anyway, sorry to be so argumentative about this, but premature optimization is a pet peeve of mine. A second pet peeve is that none of the java.util.Collections interfaces have an addAll(Object[]) method -- what were they thinking?
Alexandru Popescu
Ranch Hand

Joined: Jul 12, 2004
Posts: 995

[...] none of the java.util.Collections interfaces have an addAll(Object[]) method -- what were they thinking?


probably they expect us to dig into the API (and from time to time directly in the code - maybe we can catch some bugs ;-) ).

cheers,
--
:alex |.::the_mindstorm::.
Layne Lund
Ranch Hand

Joined: Dec 06, 2001
Posts: 3061
Wow, I didn't know my suggestion would strike up such a heated debate. However, I'm glad it did as I have learned some new things.

I have a couple of questions regarding Collections.addAll() from Java 5.0. First I see from the API docs that it uses the new varargs syntax. I haven't yet explored this feature in Java., but from my experience with varargs in C/C++, I assume this means that you can send multiple, comma-separated arguments. However, from EFH's example above, it appears that you can send an array with the list of varargs as well. Am I correct in this assumption/observation?

Second, does autoboxing allow the Collections.addAll() method from Java 5.0 work with arrays of primitives? It seems that it would, but I've encountered times where autoboxing doesn't quite work the way I expected it to. Unfortunately, I can't think of a specific example off the top of my head. Perhaps I should see if I can find it in my code at home.

Layne
[ March 13, 2005: Message edited by: Layne Lund ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24168
    
  30

Java varargs is syntactic sugar for a trailing array argument. The extra arguments get boxed if needed (to answer your second question), then packed into an array. Because of this, it's also legal to simply pass the array yourself to any method that takes varargs (to answer your first question).

I found this little book very handy as an introduction to this topic and other Tiger geegaws.
Luke Shannon
Ranch Hand

Joined: Sep 30, 2004
Posts: 239
Thanks everyone. This turned out to be an interesting thread.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Ernest Friedman-Hill:
I'm not saying that you should avoid arraycopy; I'm just saying that it's a tricky method that's best used in library code.


Full agreement! And, as I already tried to say, I think that ArrayUtils.concat makes for a very good library method...


none of the java.util.Collections interfaces have an addAll(Object[]) method -- what were they thinking?


Good question. In my experience, Java is full of such omissions, unfortunately...
Layne Lund
Ranch Hand

Joined: Dec 06, 2001
Posts: 3061
Originally posted by Ernest Friedman-Hill:
Java varargs is syntactic sugar for a trailing array argument. The extra arguments get boxed if needed (to answer your second question), then packed into an array. Because of this, it's also legal to simply pass the array yourself to any method that takes varargs (to answer your first question).

I found this little book very handy as an introduction to this topic and other Tiger geegaws.


IIRC, that book appeared for a Book Promotion somewhere around here. Unfortunately, I'm on a college-student budget, so I don't buy non-required textbooks as often as I used to. However, I graduate in May, so hopefully when I find a job and have a regular paycheck coming in, I'll have a few bucks to be able to buy more books and learn more programming stuff on the side. That is if I'm not burnt out on programming for 8+ hours a day, 5+ days a week.

Layne
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Combing String []
 
Similar Threads
Pattern matches but never replaces
Regex Issue
centralising characters
Alternative to com.google.common.base.Joiner ?
none applicable in Eclipse IDE