In article<axp%n.70738$Lj2.7209@newsfe05.iad>,
Daniel Pitts<newsgroup.spamfilter@virtualinfinity.net> wrote:
On 7/14/2010 9:42 AM, Kevin McMurtrie wrote:
In article<sbnr36ta3l2bqkf0mt23pgg6g3k8nf2ud2@4ax.com>,
Roedy Green<see_website@mindprod.com.invalid> wrote:
On 13 Jul 2010 15:01:35 GMT, Andreas Leitgeb
<avl@gamma.logic.tuwien.ac.at> wrote, quoted or indirectly quoted
someone who said :
It seems so basic that I can't believe such a feature wasn't in
the standard library:
it is part of the common11 tools for JDK 1.1+
http://mindprod.com/products1.html#COMMON11
The method is called StringTools.rep
/**
* Produce a String of a given repeating character.
*
* @param c the character to repeat
* @param count the number of times to repeat
*
* @return String, e.g. rep('*',4) returns "****"
* @noinspection WeakerAccess,SameParameterValue
*/
public static String rep( char c, int count )
{
if ( c == ' '&& count<= SOMESPACES.length() )
{
return SOMESPACES.substring( 0, count );
}
char[] s = new char[count];
for ( int i = 0; i< count; i++ )
{
s[ i ] = c;
}
return new String( s ).intern();
}
/**
* used to efficiently generate Strings of spaces of varying
length
*/
private static final String SOMESPACES = " ";
Why use intern() on the second case? It's has always been undocumented
where the pool storage is and what the cost of using it is. The only
time I use that method is when generating keys for a Properties class.
Why even use it there? I don't think I've ever seen a legitimate case
for using intern(). The *closest* I've seen to a valid use is someone
wanted to use it for synchronization based on a String key.
Sample code:
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import java.util.Properties;
public class Foo
{
private static void runLookupTest (final Properties p)
{
int c= 0;
for (int i= 0; i< 10000000; ++i)
{
c+= (p.get("org.company.services.WidgetFactory.implementor") != null) ? 1 : 0;
c+= (p.get("com.company.util.Scheduler.useTimer") != null) ? 1 : 0;
c+= (p.get("com.company.imaging.ThumbRender.filter") != null) ? 1 : 0;
}
if (c != 30000000)
throw new RuntimeException ("Bad test: " + c);
}
private static void runTestCycle (boolean warmup) throws IOException
{
//Create Properties with string keys that are not internalized
final Properties p= new Properties();
p.load(new StringReader( "org.company.services.WidgetFactory.implementor=1000\n"
+ "com.company.util.Scheduler.useTimer=true\n"
+ "com.company.imaging.ThumbRender.filter=lanczos3\n"));
//Internalized lookup of non-internalized keys
final long start1= System.nanoTime();
runLookupTest(p);
final long end1= System.nanoTime();
//Run keys through String.intern()
final Properties temp= (Properties)p.clone();
p.clear(); //put() doesn't overwrite an existing key
for (Map.Entry<Object, Object> e : temp.entrySet())
p.put(String.valueOf(e.getKey()).intern(), e.getValue());
//Internalized lookup of internalized keys
final long start2= System.nanoTime();
runLookupTest(p);
final long end2= System.nanoTime();
if (warmup)
{
System.out.println("Warmup");
}
else
{
System.out.println("Not internalized: "
+ (end1 - start1)/1000000f + " ms");
System.out.println("Internalized: "
+ (end2 - start2)/1000000f + " ms");
}
System.out.println();
}
public static void main (final String args[]) throws Exception
{
runTestCycle(true);
runTestCycle(false);
runTestCycle(false);
runTestCycle(false);
}
}
==============================================
Warmup
Not internalized: 1725.81 ms
Internalized: 794.556 ms
Not internalized: 1725.5449 ms
Internalized: 795.296 ms
Not internalized: 1725.703 ms
Internalized: 794.618 ms
probably reads fewer than 1000 properties. So, during the executions of
the program, you have saved some nanoseconds. Good for you.