Java Forum / General / February 2007
More newbie questions
Ook - 20 Feb 2007 03:57 GMT (newbie question thread consolidation thread)
Let me preface by saying I'm taking a java class, and my instructor likes to see us maximize the usage of the collections framework whenever possible. He wants an efficient oop design. I can get my code to run and do what I want, but I'm not sure if I'm maximizing the usage of the collections framework, and sometimes I make oop blunders. Hence my questions:
1) I have an ArrayList of Strings. I want to form a String that contains all of the Strings, comma delimited. This is what I do. It works, but is there are better or more correct way to do this?:
String returnValue = ""; for( String keyWord : _keywords ) returnValue = returnValue + keyWord + ", "; // Strip off the last ", " return returnValue.substring( 0, returnValue.length()-2 );
2) I have an ArrayList of Items, Item being a class with Strings and ArrayLists or TreeSets of Strings. I need to search for and create a list of items that have certain text in either the Strings, or the ArrayList/TreeSets of Strings. I can do this, my code works, but again I'm not sure I'm doing this most efficiently.
public class Item { private String _title1; private String _title2; private String _title3; private TreeSet<String> list1 = new TreeSet<String>(); ... }
It was suggested I use a HashMap, but how would I implement that with the above class, where I would have to search on different items in the class at different times? My brute force code works, where I iterate through the list with a for-each loop, checking each instance as I go through, but again may not be the most efficient way.
Boaz.Jan@gmail.com - 20 Feb 2007 05:50 GMT > (newbie question thread consolidation thread) > [quoted text clipped - 35 lines] > with a for-each loop, checking each instance as I go through, but again may > not be the most efficient way. instead of a String returnValue = ""; use StringBuffer returnValue = new StringBuffer(); and instead of doing returnValue = returnValue + keyWord + ", "; now you can use returnValue.append(keyWord); returnValue.append(", ");
more efficient then using Strings at the return you can just to returnValue.toString();
Lew - 20 Feb 2007 13:55 GMT "Ook" wrote:
>> 1) I have an ArrayList of Strings. I want to form a String that contains all >> of the Strings, comma delimited. This is what I do. It works, but is there [quoted text clipped - 5 lines] >> // Strip off the last ", " >> return returnValue.substring( 0, returnValue.length()-2 );
> instead of a > String returnValue = ""; [quoted text clipped - 8 lines] > more efficient then using Strings > at the return you can just to returnValue.toString(); In addition to Boaz.Jan's advice, you might find it easier not to trim the last comma, but to prevent it. (Underscore removed from the variable name in order to conform to Sun-recommended conventions.) Also, StringBuilder is recommended now instead of StringBuffer.
if ( keywords.size() == 0 ) { return "'; // or null, as requirements specify } StringBuilder ret = new StringBuilder( keywords.get(0) ); for ( int ix = 1; ix < keywords.size(); ++ix ) { ret.append( ", ").append( keywords.get(ix) ); } return ret.toString();
Is your List guaranteed not to have null entries?
There is also a way to express the loop using an Iterator, which your professor will no doubt like.
- Lew
Ook - 20 Feb 2007 20:20 GMT > instead of a > String returnValue = ""; [quoted text clipped - 8 lines] > more efficient then using Strings > at the return you can just to returnValue.toString(); How about removing the final ", "? Is there a way, in the for-each loop, to tell if we are on the last item in the list? In other languages I just strip the trailing ", ", but this is a school assignment, and clever usage of the collections framework impresses the instructor :-P
Lars Enderin - 20 Feb 2007 22:53 GMT Ook skrev:
>> instead of a >> String returnValue = ""; [quoted text clipped - 13 lines] > the trailing ", ", but this is a school assignment, and clever usage of the > collections framework impresses the instructor :-P You could treat the first item specially, and add ", " before any following item. Or have a boolean first, initialized to true, which is used to decide if a ", " is needed.
Daniel Pitts - 21 Feb 2007 00:24 GMT > > instead of a > > String returnValue = ""; [quoted text clipped - 13 lines] > the trailing ", ", but this is a school assignment, and clever usage of the > collections framework impresses the instructor :-P StringBuilder returnValue = new StringBuilder(); for (String item: items) { if (returnValue.size() != 0) { returnValue.append(", "); } returnValue.append(item); }
Or, instead of using for-each:
Iterator<String> iterator = items.iterator(); if (iterator.hasNext()) { StringBuilder returnValue = new StringBuilder(iterator.next()); while (iterator.hasNext()) { returnValue.append(", ").apend(iterator.next()); } }
Oliver Wong - 21 Feb 2007 16:19 GMT > StringBuilder returnValue = new StringBuilder(); > for (String item: items) { [quoted text clipped - 3 lines] > returnValue.append(item); > } Nice! I had never thought of that.
- Oliver
Oliver Wong - 21 Feb 2007 15:22 GMT >> instead of a >> String returnValue = ""; [quoted text clipped - 13 lines] > strip the trailing ", ", but this is a school assignment, and clever usage > of the collections framework impresses the instructor :-P I can't think of an easy way to *not* add the ", " using a for-each loop, and adding it, and later removing it, seems inelegant to me. So I'd recommend using an explicit Iterator, e.g.
StringBuffer sb = new StringBuffer(); Iterator myIterator = myCollect.getIterator(); /*I forget the name of the method to get the iterator, and too lazy to look it up right now*/ while (myIterator.hasNext()) { Object whatever = myIterator.next() sb.append(whatever.toString()); if (myIterator.hasNext()) { sb.append(", "); } }
- Oliver
Chris Uppal - 21 Feb 2007 15:59 GMT > StringBuffer sb = new StringBuffer(); > Iterator myIterator = myCollect.getIterator(); /*I forget the name of the [quoted text clipped - 6 lines] > } > } I find that ugly -- the double call to hasNext() somehow makes the loop a lot harder to understand than a simple boolean flag or Daniel's version using returnValue.length().
Yet another way -- which is also ugly, but in some sense more direct than anything shown so far:
StringBuilder returnValue = new StringBuilder();
.String separator = ""; for (String item: items) { returnValue .append(separator) .append(item); separator := ", "; }
"Look Ma, no conditionals !"...
-- chris
Daniel Pitts - 21 Feb 2007 18:18 GMT On Feb 21, 7:59 am, "Chris Uppal" <chris.up...@metagnostic.REMOVE- THIS.org> wrote:
> separator := ", "; Um, somebody has reverted to their pascal days. :-)
Chris Uppal - 22 Feb 2007 12:36 GMT [me:]
> > separator := ", "; > > Um, somebody has reverted to their pascal days. :-) Oops!
(Actually it's a carry-over from my day-to-day programming in Smalltalk, not from some murky past as a Pascal user -- I have never used Pascal (yippee!). I occasionally mistype self.someMethod() instead of this.someMethod() too ;-)
-- chris
Boaz.Jan@gmail.com - 20 Feb 2007 06:12 GMT > (newbie question thread consolidation thread) > [quoted text clipped - 35 lines] > with a for-each loop, checking each instance as I go through, but again may > not be the most efficient way. sorry for spliiting the post.. iterating as you did is good enough. if you get a ref to a String object (not a string value!!) and you want to find in which item it is you can make a method that itrates in all the Items and checks the TreeSet.contains(Object 0) method http://java.sun.com/j2se/1.5.0/docs/api/java/util/TreeSet.html#contains(java.lan g.Object)
a HashMap let you set you Key-Value pairs you can set the String Value as your Key and set the String object instance as your value as so key = "string to search" value = strSomeString and then when you access the HashMap.get("string to search); it will return you the strSomeString how does it help you? well its make your bruteforce iteration more efficient instead of iterating the main collection and every sub-collection within that collection you only iterating the main collection and the sub-collection are now being accessed with a constant time preformance - like an array
you should check the fine prints of the HashMap.get(Object o) method about null values before ypu start implementing it http://java.sun.com/j2se/1.5.0/docs/api/java/util/HashMap.html#get(java.lang.Object)
Lew - 20 Feb 2007 14:07 GMT > a HashMap let you set you Key-Value pairs > you can set the String Value as your Key and set the String object > instance as your value > as so > key = "string to search" value = strSomeString The "str" prefix is a bit counterproductive.
Map<String, String> map = new HashMap<String, String>; ... map.put( someString, someString );
This is not so useful yet. (It is essentially equivalent to a HashSet, not that that is relevant.) You need the string to look itself up.
I assume you are searching for any string in the data store that has the search string as a substring? You didn't exactly say what the match criterion is.
public void init() { for ( String targetTerm : setOfAllPossibleTargetTerms ) { for ( String searchTerm : setOfAllPossibleSearchTerms ) { if ( targetTerm.indexOf( searchTerm ) >= 0 ) { map.put( searchTerm, targetTerm ); } } } }
public String search( String ) { return map.get( searchTerm ); }
This can be quite an exercise if the universe of search and target terms is large, and will fail utterly if the same search term could match more than one target term.
> and then when you access the HashMap.get("string to search); > it will return you the strSomeString [quoted text clipped - 8 lines] > about null values before ypu start implementing it > http://java.sun.com/j2se/1.5.0/docs/api/java/util/HashMap.html#get(java.lang.Object) A better approach might be to google on "suffix tree".
- Lew
Boaz.Jan@gmail.com - 20 Feb 2007 18:54 GMT > > key = "string to search" value = strSomeString > > The "str" prefix is a bit counterproductive. that was to emphasis that it is an Object in the Value oppsing to the Key which is a String Value but never mind the str prefix is irelevant
Mark Jeffcoat - 20 Feb 2007 06:28 GMT (You told us this was homework, and you actually wrote some code. What an excellent beginning.)
> 1) I have an ArrayList of Strings. I want to form a String that contains all > of the Strings, comma delimited. This is what I do. It works, but is there [quoted text clipped - 5 lines] > // Strip off the last ", " > return returnValue.substring( 0, returnValue.length()-2 ); I don't have any real problem with this, but I think making returnValue a StringBuilder is a minor improvement.
If this were a very, very long list, I'd look for a way to avoid that substring() at the end. I don't think that's worth complicating the logic; your version is fine.
(For future reference: you could have written line 3 as returnValue += keyWord + ", ";
But use StringBuilder instead.)
> 2) I have an ArrayList of Items, Item being a class with Strings and > ArrayLists or TreeSets of Strings. I need to search for and create a list of [quoted text clipped - 10 lines] > ... > } OOP aside: go ahead and get in the habit now of talking about (and writing) designs in the most abstract way that still expresses your intent. That is, in this example I'd say you have a List of Items, instead of an ArrayList of Items. In fact, unless order is important, you may well have a Collection.
Consistently follow that rule, and not only will your methods work on more kinds of things, but someone reading your code will know that you used TreeSet there because you specifically need a set that is ordered.
Oh; "TreeSet<String> list1" just can't be the best thing. Sets and Lists are different kinds of Collections, and you want to be very clear as to what you're talking about. (Unless you don't care, because any kind of Collection will work.)
> It was suggested I use a HashMap, but how would I implement that with the > above class, where I would have to search on different items in the class at > different times? My brute force code works, where I iterate through the list > with a for-each loop, checking each instance as I go through, but again may > not be the most efficient way. If I understand you correctly, you want to write a function that takes a Collection of Items, and returns another Collection of Items that contains all the Items that match a String. (With no restrictions at all on what that String can be.)
My Item might have a static method like public static Collection<Item> filter(Collection<Item> items, String s) {
Collection<Item> passed = new ArrayList(); for (Item i : items) { if (i.matches(s)) { passed.add(i); } } return passed; }
That's probably pretty much the same as what you've got now.
I can't think of any way to use a Map that isn't silly. If a Map's in the best answer, then either I've misunderstood the problem, or I'm going to be very surprised by someone else's answer.
 Signature Mark Jeffcoat Austin, TX
Nigel Wade - 20 Feb 2007 12:07 GMT "Ook" <Ook Don't send me any freakin' spam at zootal dot com delete the Don't send me any freakin' spam> wrote:
> (newbie question thread consolidation thread) > [quoted text clipped - 13 lines] > // Strip off the last ", " > return returnValue.substring( 0, returnValue.length()-2 ); If you really want to maximize your use of the Collections framework then look at AbstractCollection.toString()...
> 2) I have an ArrayList of Items, Item being a class with Strings and > ArrayLists or TreeSets of Strings. I need to search for and create a list of [quoted text clipped - 16 lines] > with a for-each loop, checking each instance as I go through, but again may > not be the most efficient way. Collections.binarySearch() perhaps?
http://java.sun.com/docs/books/tutorial/collections/algorithms/index.html
 Signature Nigel Wade, System Administrator, Space Plasma Physics Group, University of Leicester, Leicester, LE1 7RH, UK E-mail : nmw@ion.le.ac.uk Phone : +44 (0)116 2523548, Fax : +44 (0)116 2523555
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|