Prev: Const correctness (was Re: Oppinion on 'least priviledge','const correctness', etc.)
Next: How to remotely construct a remote object with RMI
From: Lew on 22 Jul 2010 13:26 harryajh wrote: >>> ResultSet rs = ps.executeQuery(); >>> >>> while (true) >>> { >>> ret = new myBean(); > Class names should start with an upper-case letter. >>> String propName = rs.getString(2); >>> >>> if (propName.equalsIgnoreCase("licence_number")) >>> { >>> ret.setLicenceNo(rs.getString(3)); >>> } >>> else if (propName.equalsIgnoreCase("return_requirement_id")) >>> { >>> ret.setReturnReqId(rs.getString(3)); >>> } >>> } > It looks like you might need to revise your database query or schema - the same column of the result should not mean different things. But since it does ... Alan Gutierrez wrote: > I read the OPs uncompilable code as being a loop over a result set, even > though it has that nonsense while(true) which really should read while > (rs.next()), but then maybe the OP really wants an infinite loop over a > single row of a result set. In which case, it doesn't matter how much > faster it runs. > One way would be to have an enum keyed to the different possible values from column 2 with a service method to set the correct value from column 3, something similar to this uncompiled (let alone tested) idea: public enum ColumnSetter { licence_number { @Override public void setColumn3( MyBean ret, String value ) { ret.setLicenceNo( value ); } }, return_requirement_id { @Override public void setColumn3( MyBean ret, String value ) { ret.setReturnReqId( value ); } }; abstract public void setColumn3( MyBean ret, String value ); } Then the client code is something along the uncompiled, untested lines of: ... PreparedStatement ps = Connection.prepareStatement( ... ); try { // set up query parms MyBean ret = new MyBean(); for( ResultSet rs = ps.executeQuery(); rs.next(); ) { ColumnSetter cs = ColumnSetter.valueOf( rs.getString( 2 )); cs.setColumn3( ret, rs.getString( 3 )); // risks NPE } return ret; } finally { ps.close(); } You can create a replacement method in ColumnSetter for valueOf() that is case-insensitive. I usually define an instance override 'toString()' and static 'fromString()' for enums. (As a riff on "RAII" I call the above try...finally idiom variously "RRIG" or "RRIF" or "RRID", respectively "Resource Release is Guaranteed", "Resource Release in Finally" or "Resource Release in Deallocation". Your votes welcomed.) -- Lew
From: Andreas Leitgeb on 22 Jul 2010 14:38 harryajh <harryreg_uk(a)yahoo.co.uk> wrote: > if (propName.equalsIgnoreCase("licence_number")) > else if (propName.equalsIgnoreCase("return_requirement_id")) One thing to avoid unnecessary waste might be to "toLowerCase()" once, and then use plain .equals() for comparisons. Next step would be to look up the toLowerCase()'d property name in a HashMap, that has all 10 strings associated with a small integer, which you then use in a switch(...){...} to get the appropriate method called on the MyBean for each number. The "OO" way, would be to have some interface like interface Storer { void store(MyBean b,String s); } and in the HashMap you associate anonymous Storer-implementations: Map<String,Storer> m = new HashMap<String,Storer>(); m.put("licence_number",new Storer() { public void store(MyBean b,String s) { b.setLicenceNo(s); } } ); m.put("return_requirement_id",new Storer() { public void store(MyBean b,String s) { b.ret.setReturnReqId(s); } } ); // ... ditto for the further 8 mappings MyBean b = new MyBean(); Then, inside the loop: m.get(rs.getString(2).toLowerCase()).store(b,rs.getString(3)); Well, actually you may want to break this up into separate statements storing intermediate results in local variables and do null-checks where appropriate. For best encapsulation, you could add a method to MyBean, that takes the Property's name and new value, and does the HashMap-lookup and invocation of the obtained Storer. The HashMap itself would also be maintained by MyBean and created and populated in the static initializer, or lazily on first use. I do not claim, that any of these would actually make your whole program faster, but I dislike those if-chains, anyway, so even if your program doesn't end up faster, I think those alternatives would still be worth considering. PS: "myBean" was a bad class-name and "GetString" is not a method of ResultSet, so I changed them.
From: Jim Janney on 22 Jul 2010 16:21 Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> writes: > harryajh <harryreg_uk(a)yahoo.co.uk> wrote: >> if (propName.equalsIgnoreCase("licence_number")) >> else if (propName.equalsIgnoreCase("return_requirement_id")) > > One thing to avoid unnecessary waste might be to "toLowerCase()" once, > and then use plain .equals() for comparisons. It depends. If you look at the code for String.equalsIgnoreCase, it doesn't have that much overhead compared to .equals. If there are 10 choices that are all equally likely, each iteration of the loop will average 5 comparisons, so you're balancing the extra cost of 5 case-insensitive comparisons against the possibility of creating a new object. Note that equals or equalsIgnoreCase often return false immediately after comparing lengths. If the choices are *not* all equally likely, you can cut down on the average number of comparisons by testing for the most common values first. -- Jim Janney
From: Jim Janney on 22 Jul 2010 16:24 harryajh <harryreg_uk(a)yahoo.co.uk> writes: > I have to process a large number of database records, examine a column > value (can be 10 different values) and set a bean's property depending > on that fields values e.g (vastly cut down) > > ResultSet rs = ps.executeQuery(); > > while (true) > { > ret = new myBean(); > > String propName = rs.getString(2); > > if (propName.equalsIgnoreCase("licence_number")) > { > ret.setLicenceNo(rs.getString(3)); > } > else if (propName.equalsIgnoreCase("return_requirement_id")) > { > ret.setReturnReqId(rs.getString(3)); > } > } > > Hopefully its relativily easy to follow what I'm trying to do, my big > problem though is using a "String" to hold the fields value, this > obviously is not a good idea and surely for performance reasons > neither would - > > if (rs.getString(2).equalsIgnoreCase("licence_number")) > > or wouldn't it make much difference getting the field value up to 10 > times? > > A bit lost as to what's the best/efficient way to do this, should I > use a StringBuffer every time? would it be garbage collected? - any > other ideas? > > thanks Your first mistake is thinking that anything you do here will have a measurable effect on performance. It won't: the run time will always be dominated by the call to ps.executeQuery(). However, there's another mistake that I can't bring myself to ignore, so: no, using a String to hold the field's value is not wrong, and using a StringBuilder will not help you. -- Jim Janney
From: Lew on 22 Jul 2010 21:17
harryajh writes: >> A bit lost as to what's the best/efficient way to do this, should I >> use a StringBuffer every time? would it be garbage collected? - any >> other ideas? Jim Janney wrote: > However, there's another mistake that I can't bring myself to ignore, > so: no, using a String to hold the field's value is not wrong, and > using a StringBuilder will not help you. It's even worse than that. He asked about using a StringBuffer. -- Lew |