📜 ⬆️ ⬇️

Java string processing Part I: String, StringBuffer, StringBuilder

Introduction


What do you know about string handling in Java? How much of this knowledge and how deep and relevant are they? Let's try with me to sort out all the issues related to this important, fundamental and often used part of the language. Our small guide will be divided into two publications:

  1. String, StringBuffer, StringBuilder (string implementation)
  2. Pattern, Matcher (regular expressions)

The implementation of strings in Java is represented by three main classes: String , StringBuffer , StringBuilder . Let's talk about them.

String


A string is an object that represents a sequence of characters. To create and manipulate Java strings, the platform provides a public final (cannot have subclasses) java.lang.String class. This class is immutable ( immutable ) - the created object of class String cannot be changed. You might think that methods have the right to modify this object, but this is not true. Methods can only create and return new lines in which the result of an operation is stored. The immutability of strings provides a number of possibilities:


Creature


We can create an object of class String in several ways:
')
1. Using string literals:

String habr = "habrahabr"; 

A string literal is a sequence of characters enclosed in double quotes. It is important to understand that whenever you use a string literal, the compiler creates an object with the value of this literal:

 System.out.print("habrahabr"); //       

2. With the help of constructors:

 String habr = "habrahabr"; char[] habrAsArrayOfChars = {'h', 'a', 'b', 'r', 'a', 'h', 'a', 'b', 'r'}; byte[] habrAsArrayOfBytes = {104, 97, 98, 114, 97, 104, 97, 98, 114}; String first = new String(); String second = new String(habr); 

Unless a copy of the string is explicitly required, the use of these constructors is undesirable and is not necessary because the strings are immutable. Constant construction of new facilities in this way can lead to lower productivity. It is better to replace them with similar initializations using string literals.

 String third = new String(habrAsArrayOfChars); // "habrahabr" String fourth = new String(habrAsArrayOfChars, 0, 4); // "habr" 

Constructors can form a string object using an array of characters. The array is copied; the static methods copyOf and copyOfRange (copying the entire array and its part (if the 2nd and 3rd parameters of the constructor are specified) respectively) of the Arrays class, which in turn use the platform-dependent implementation of System.arraycopy, are used for this .

 String fifth = new String(habrAsArrayOfBytes, Charset.forName("UTF-16BE")); //      "桡扲慨慢 " 

You can also create a string object using a byte array. Additionally, you can pass a Charset class parameter that will be responsible for the encoding. The array is decoded using the specified encoding (if not specified - Charset.defaultCharset () is used, which depends on the encoding of the operating system) and, further, the resulting array of characters is copied into the value of the object.

 String sixth = new String(new StringBuffer(habr)); String seventh = new String(new StringBuilder(habr)); 

Well, finally, constructors use StringBuffer and StringBuilder objects , their values ​​( getValue () ) and length () ( ) to create a string object. These classes will be introduced later.

Examples of the most commonly used constructors of the String class are given, in fact, there are fifteen of them (two of which are marked as deprecated ).

Length


An important part of each line is its length. You can find it by accessing the String object using the accessor method ( accessor method ) length () , which returns the number of characters in a string, for example:

 public static void main(String[] args) { String habr = "habrahabr"; //    int length = habr.length(); //        'h'  "habrahabr" char searchChar = 'h'; boolean isFound = false; for (int i = 0; i < length; ++i) { if (habr.charAt(i) == searchChar) { isFound = true; break; //   } } System.out.println(message(isFound)); // Your char had been found! // , ,    indexOf System.out.println(message(habr.indexOf(searchChar) != -1)); // Your char had been found! } private static String message(boolean b) { return "Your char had" + (b ? " " : "n't ") + "been found!"; } 

Concatenation


Concatenation is a string merging operation that returns a new string, which is the result of merging the second string with the end of the first. The operation for a String object can be performed in two ways:

1. The concat method

 String javaHub = "habrhabr".concat(".ru").concat("/hub").concat("/java"); System.out.println(javaHub); //  "habrhabr.ru/hub/java" //     concat private static String message(boolean b) { return "Your char had".concat(b ? " " : "n't ").concat("been found!"); } 

It is important to understand that the concat method does not change the string, but only creates a new one as a result of merging the current and passed as a parameter. Yes, the method returns a new String object, so such long strings are possible.

2. Overloaded operators " + " and " + = "

 String habr = "habra" + "habr"; // "habrahabr" habr += ".ru"; // "habrahabr.ru" 

These are one of the few overloaded operators in Java - the language does not allow overloading operations for objects of user classes. The "+" operator does not use the concat method ; the following mechanism is used here:

 String habra = "habra"; String habr = "habr"; //     String habrahabr = habra + habr; //     String habrahabr = new StringBuilder()).append(habra).append(habr).toString(); //    StringBuffer 

Use the concat method if you only need to merge once, for other cases it is recommended to use either the " + " operator or StringBuffer / StringBuilder . It is also worth noting that getting NPE ( NullPointerException ) if one of the operands is null is impossible using the " + " or " + = " operator, which cannot be said about the concat method, for example:

 String string = null; string += " habrahabr"; // null   "null",   "null habrahabr" string = null; string.concat("s"); //   NullPointerException 

Formatting


The String class provides the ability to create formatted strings. The static format method is responsible for this, for example:

 String formatString = "We are printing double variable (%f), string ('%s') and integer variable (%d)."; System.out.println(String.format(formatString, 2.3, "habr", 10)); // We are printing double variable (2.300000), string ('habr') and integer variable (10). 

Methods


Thanks to a variety of methods, it is possible to manipulate a string and its characters. There is no point in describing them here because Oracle has good articles about manipulating and comparing strings. Also at your hand is always their documentation . I wanted to note the new static join method, which appeared in Java 8. Now we can conveniently combine several strings into one using a separator (the java.lang.StringJoiner class was added, which is responsible for it), for example:

 String hello = "Hello"; String habr = "habrahabr"; String delimiter = ", "; System.out.println(String.join(delimiter, hello, habr)); //   System.out.println(String.join(delimiter, new ArrayList<CharSequence>(Arrays.asList(hello, habr)))); //    "Hello, habrahabr" 

This is not the only class change in Java 8. Oracle reports a performance improvement in the String constructor (byte [], *) and the getBytes () method.

Transformation


1. Number per line

 int integerVariable = 10; String first = integerVariable + ""; //     String second = String.valueOf(integerVariable); //    valueOf  String String third = Integer.toString(integerVariable); //   toString - 

2. Row to number

 String string = "10"; int first = Integer.parseInt(string); /*    (primitive type)   parseX  -,  Xxx -      ( parseInt) */ int second = Integer.valueOf(string); //   wrapper     


Stringbuffer


The lines are unchanged, so their frequent modification leads to the creation of new objects, which in turn consumes precious memory. To solve this problem, the java.lang.StringBuffer class was created, which allows you to work more effectively on the modification of the string. The class is mutable , that is, mutable - use it if you want to change the contents of the string. StringBuffer can be used in multi-threaded environments, since all the necessary methods are synchronized.

Creature


There are four ways to create an object of class StringBuffer . Each object has its own capacity ( capacity ), which is responsible for the length of the internal buffer. If the length of the string that is stored in the internal buffer does not exceed the size of this buffer ( capacity ), then there is no need to allocate a new buffer array. If the buffer overflows - it automatically becomes larger.

 StringBuffer firstBuffer = new StringBuffer(); // capacity = 16 StringBuffer secondBuffer = new StringBuffer("habrahabr"); // capacity = str.length() + 16 StringBuffer thirdBuffer = new StringBuffer(secondBuffer); //  -  ,   CharSequence StringBuffer fourthBuffer = new StringBuffer(50); //  capacity 

Modification


In most cases, we use StringBuffer to perform append , insert ( insert ) and delete ( subst ) operations multiple times. It's all very simple, for example:

 String domain = ".ru"; //     String  StringBuffer buffer = new StringBuffer("habrahabr"); // "habrahabr" //     buffer.append(domain); // "habrahabr.ru" //   buffer.delete(buffer.length() - domain.length(), buffer.length()); // "habrahabr" //         insert buffer.insert(buffer.length(), domain); // "habrahabr.ru" 

All other methods for working with StringBuffer can be found in the documentation .

Stringbuilder


StringBuilder - a class that represents a variable character sequence. The class was introduced in Java 5 and has a completely identical API with a StringBuffer . The only difference is that StringBuilder is not synchronized. This means that its use in multi-threaded environments is undesirable. Therefore, if you are working with multithreading, StringBuffer is perfect for you , otherwise use StringBuilder , which works much faster in most implementations. Let's write a small test for comparing the speed of work of these two classes:

 public class Test { public static void main(String[] args) { try { test(new StringBuffer("")); // StringBuffer: 35117ms. test(new StringBuilder("")); // StringBuilder: 3358ms. } catch (java.io.IOException e) { System.err.println(e.getMessage()); } } private static void test(Appendable obj) throws java.io.IOException { //      long before = System.currentTimeMillis(); for (int i = 0; i++ < 1e9; ) { obj.append(""); } //      long after = System.currentTimeMillis(); //   System.out.println(obj.getClass().getSimpleName() + ": " + (after - before) + "ms."); } } 

Thanks for attention. I hope the article will help to learn something new and push to remove all gaps in these issues. All additions, clarifications and criticism are welcome.

Source: https://habr.com/ru/post/260767/


All Articles