From JavaProgramming '''Arrays and strings in Java''' ''Warning: There be dragons here...'' '''[I just refactored them away, hopefully I got them all]''' ''Thanks, actually I meant that the topic itself is fraught with traps, pitfalls, and landmines. See JavaArraysBreakTypeSafety and JavaArraysShouldBeFirstClassObjects, for example.'' ''Arrays'' Arrays have constant size: int arr[] = new int[3]; If more space is needed at run time, a new array object must be created, and you must manually copy any data you still need from the old array. Use collection classes, such as java.util.A''''''rrayList for dynamic arrays. : ''The similar legacy class java.util.Vector has some overhead because it is completely thread-safe. If you do not require thread-safety at that level, the modern equivalent java.util.A''''''rrayList does not pay the synchronization cost, but can still be wrapped with a synchronization wrapper using java.util.Collections.synchronizedList(). The cost of acquiring a lock on a monitor in the current virtual machines is much lower than it once was, so although the penalty is low now, it was once quite severe.'' Arrays may be multidimensional: int arr2[][] = new int[3][2]; Array declarations may have the [] before or after the variable name: int[] foo; int bar[]; Arrays may be initialized in code: int ages[] = { 3, 6, 7 }; Multidimensional arrays may be non-rectangular: int ragged[][] = { {1, 2}, {3, 4, 5}, {6} }; ''Strings'' The String class has no index-operator, use method charAt(): //char c = s[0]; // Index operator not supported char c = s.charAt(0); // Ok The + operator performs concatenation in expressions that have a String operand. Beyond this compiler-based "overloading", operator overloading is not supported in Java. Thus, strings may be concatenated with other strings or expressions of other types: String s = "number: " + 10; String concatenation with other object types implicitly invokes toString() on the operand. Date d = new Date(); String s = "now: " + d; Prints something like: "now: Wed Jun 26 14:25:08 MDT 2002" For Strings -- and indeed all object types -- the equality operator (==) tests for object identity, not lexical equivalence. Use equals() to test for lexical equivalence between strings, and use == only to test if two references point to the exact same string instance: String s1 = "123", s2 = s1, s3 = new String(s1); System.out.println(s1 == s2); // prints true System.out.println(s1 == s3); // prints false System.out.println(s1.equals(s2)); // prints true System.out.println(s1.equals(s3)); // prints true It is possible to use the intern() function to use == for comparison: s1.equals(s2) if and only if s1.intern() == s2.intern(). Of course the gain is to store the result of s.intern(), and then get faster comparisons. --------------------------- : Interesting sidebar on the original text: this example would not demonstrate what the original author intended. String s1 = "123", s2 = "123"; // boolean b = (s1 == s2); // Equality operator not supported '''[[wrong]]''' boolean b = s1.equals(s2); // OK! : Sun's compiler actually distills all identical string literals in a class down to a single string object in the constant pool of that class. The == test shown here would actually evaluate as true! The example was rewritten, in a somewhat less lucid form, for this reason. --------------------------- Conventional wisdom has advised to use S''''''tringBuffer profusely, however such advice is mostly outdated since current Java compilers will use S''''''tringBuffer in the generated code. The original exhange retained below tells most of the story, and I will return with more examples. The current compilers do a pretty good job on complex string expressions. final long yarms = 3; String s = "There are " + 4 + " arms on the capital letter " + 'X' + " and " + " there are only " + yarms + " on the letter " + 'Y' + "."; becomes String s = "There are 4 arms on the capital letter X and there are only 3 on the letter Y."; Don't trust me on this... use ''javap -c'' and see for yourself! (''javap'' comes with your JDK.) For me, the moral of the String/S''''''tringBuffer story is to be careful with performance advice from Java book authors. Most Java performance tricks fall out of date as the compilers approach professional quality and as the runtime environments improve. (In fact, some of the tricks that improved performance under earlier Java releases actually hinder performance under later versions of Java!) --------------------------- '''[original exchange on String and StringBuffer]]''' : "Use class S''''''tringBuffer for better performance. String concatenation will result in a new string object, whereas the content of a S''''''tringBuffer object is mutable: String s = "abc"; s += "def"; // Creating new String object S''''''tringbuffer sb = "abc"; sb.append("def"); // S''''''tringBuffer object now contains "abcdef" : Note, that String concatenation uses a String''''''Buffer internally, the above is executed as such: String s = "abc"; String''''''Buffer sb = new String''''''Buffer(s); sb.append("def"); s=sb.toString(); : and therefore there is no performance benefit in most cases, unless you're concatting many, ''many'' strings; String''''''Buffer is ''not'' a String, and therefore cannot be used ''in place'' of a String, but starting with JDK 1.4 String and String''''''Buffer both implement the (small) interface Char''''''Sequence. ---- Here is a test program for trying out array and string functions: '''[Dragons remain]''' /* T''''''estString.java */ public class T''''''estString { public static void main(String[] args) { int arr[] = new int[3]; arr[0] = 1; arr = new int[4]; // Data lost on creation of a new array System.out.println("" + arr[0]); // Output = 0 String s = "123"; // if(s[0] == '1') // Index operator not supported if(s.charAt(0) == '1') // Ok, output: true System.out.println("true"); else System.out.println("false"); '''// or to a Java programmer: System.out.println(s.charAt(0) == '1'); :-)''' // Arithmetic operators supported for String s = "number: " + 10; // Implicit call to String() and Integer.toString() '''[actually, it gets folded together at compile time]''' System.out.println(s); // output: number: 10 s = Integer.toString(10); // Explicit conversion System.out.println(s); // output: 10 String s1 = "123", s2 = "123"; '''// [Grrrrowwl]''' // if(s1 == s2) System.out.println("true"); // Equality operator not supported '''// ["not supported" overstates things... "doesn't do what some might expect".]''' if(s1.equals(s2)) // Output: true System.out.println("true"); else System.out.println("false"); // Use S''''''tringBuffer for better performance '''[ummm...]''' s = "abc"; s += "def"; // Creating new String object System.out.println(s); // output: abcdef S''''''tringBuffer sb = new S''''''tringBuffer("abc"); sb.append("def"); // S''''''tringBuffer object now contains "abcdef" System.out.println(sb); // output: abcdef } } ---- S''''''tringBuffer improves upon String when a loop comes into play. String[] term = new String[1000]; for (int i = 0; i < term.length; ++i) { term[i] = "term " + i + ","; } // Now start timing. String stringConcatenation = ""; for (int i = 0; i < term.length; ++i) { stringConcatenation += term[i]; } // Compare to: S''''''tringBuffer stringBufferConcatenation = new S''''''tringBuffer(); for (int i = 0; i < term.length; ++i) { stringBufferConcatenation.append(term[i]); } String sbFinal = stringBufferConcatenation.toString(); It would be a very sophisticated compiler that converted the String loop to the S''''''tringBuffer form. And, if the variables were attributes instead of method-local variables, it wouldn't even be correct, considering the possibilities of multi-threading. --EricJablow