# Java String

An immutable, iterable, non-primitive data type, consisting of characters, implementing CharSequence, Serializable, Comparable&lt;String&gt; interfaces.

```java
String name = "Fossery";
```

## Use variable values to create Strings

### Concatenation

Using **+** operator:

```java
String hello = "Hello " + name + "!";
```

Using **.concat(String str)** method:

```java
String hello2 = "Hello ".concat(name).concat("!"); // concat() can only have one argument
```

Using **StringBuilder** or **StringBuffer** (the **.append()** and **.toString()** methods of both classes give the same result):

```java
StringBuilder sb = new StringBuilder();
sb.append("Hello ");
sb.append(name);
sb.append("!");
String hello3 = sb.toString();

// or

StringBuilder sb = new StringBuilder();
sb.append("Hello ").append(name).append("!"); // append() can only have one argument
String hello3 = sb.toString();
```

### String literal

Using **String.format(String pattern, Object... arguments)**:

```java
String hello4 = String.format("Hello %s!", name);
```

Using **MessageFormat.format(String pattern, Object... arguments)**:

```java
import java.text.MessageFormat;

String hello5 = MessageFormat.format("Hello {0}!", name);
```

## Get length of String

Using **.length()** method:

```java
// name = "Fossery"
int nameLength = name.length(); // 7
```

## Compare two Strings

Using **.equals(Object obj)** method - return true if the two strings match, false if not:

```java
boolean doTheyMatch = name.equals("Fossery"); // true
```

Using **.compareTo(String str)** method - compare lexicografically, return negative integer if original String precedes argument String, 0 if they match, positive integer if argument String precedes original String:

```java
int nameComparison = name.compareTo("Fossery"); // 0
```

> **Important!** \\== operator shouldn't be used for comparing Strings (or any objects of non-primitive type) in most cases, because it compares the references of the two Strings, so "Fossery" \\== "Fossery" will return false, because those are two different String objects, regardless of all their characters matching.

### Ignoring case

Using **.equalsIgnoreCase(String str)** or **.compareToIgnoreCase(String str)** - work similarly to .equals(Object obj) and .compareTo(String str).

## Get character at a specific index

Using **.charAt(int index)** method:

```java
char initialLetter = name.charAt(0); // 'F'
```

## Get a substring

Using **.substring(int beginIndex, int endIndex)** method - endIndex is optional, selects all characters from beginIndex to the end of the String if not provided:

```java
String foss = name.substring(0, 4); // "Foss"
String ery = name.substring(4); // "ery"
```

## Search a character in a String

Using **.indexOf(char c)** method - return index of first occurrence, or -1 if not found (optional fromIndex argument can be provided to start search in that position):

```java
int firstS = name.indexOf('s'); // 2
```

Using **.lastIndexOf(char c)** method - return index of last occurrence, or -1 if not found (optional fromIndex argument can be provided to start search in that position):

```java
int lastS = name.lastIndexOf('s'); // 3
```

## Search a substring in a String

Using **.indexOf(String c)** or **.lastIndexOf(String c)**: use as shown in "Search a character in a String", but pass String instead of char

Using **.contains(CharSequence s)** method - return boolean:

```java
boolean isHeFoss = name.contains("Foss"); // true
```

Using **.startsWith(String s)** method - return boolean (true only if substring is at the start of String):

```java
boolean startsWithFoss = name.startsWith("Foss"); // true
```

Using **.endsWith(String s)** method - return boolean (true only if substring is at the end of String):

```java
boolean endsWithFoss = name.endsWith("Foss"); // false
```

## Convert char to String

Using **String.valueOf(char character)** - most efficient method:

```java
// initialLetter = 'F'
String initialLetterStr = String.valueOf(initialLetter); // "F"
```

Using **Character.toString()**:

```java
String initialLetterStr2 = new Character(initialLetter).toString(); // "F"

// or

String initialLetterStr3 = Character.toString(initialLetter); // "F" - makes internal call to String.valueOf()
```

Using **+** operator ([not recommended!](https://soflow.nerdvpn.de/questions/8172420/how-to-convert-a-char-to-a-string#8172439)):

```java
String initialLetterStr3 = "" + initialLetter; // "F"
```

## Iterate through characters of String

Using **for** loop - most optimal:

```java
for (int i = 0; i < name.length(); i++) {
  System.out.println(name.charAt(i));
}

// performance-optimized for loop (evaluate name.length() only once):

for (int i = 0, n = name.length(); i < n; i++) {
  System.out.println(name.charAt(i));
}
```

Converting String to char array and using **for-each** loop - more readable, but less optimal:

```java
for (char letter : name.toCharArray()) {
  System.out.println(letter);
}
```

Using **.chars()** or **.codePoints()**, with **.forEachOrdered()** - from java 8:

```java
name.chars().forEachOrdered(i -> System.out.print((char)i));
name.codePoints().forEachOrdered(i -> System.out.print((char)i));
```

## Join multiple Strings into a single String

Using **String.join(CharSequence delimiter, CharSequence... elements)**:

```java
String shoppingList = String.join(", ", "apple", "bread", "milk"); // "apple, bread, milk"
```

Using **StringJoiner**:

```java
import java.util.StringJoiner;

String shoppingList2 = new StringJoiner(", ").add("apple").add("bread").add("milk").toString(); // "apple, bread, milk"
```

### Join elements of String array, List and other Iterables

Using **String.join(CharSequence delimiter, Iterable&lt;? extends CharSequence&gt; elements)**:

```java
String[] shoppingListArr = new String[]{"apple", "bread", "milk"};
String shoppingListStr = String.join(", ", shoppingList); // "apple, bread, milk"
```

Using **stream**:

```java
import java.util.Arrays;
import java.util.ArrayList;
import java.util.stream.Collectors;

// for Collections

ArrayList<String> shoppingArrayList = new ArrayList<>(Arrays.asList("apple", "bread", "milk"));
String shoppingList3 = shoppingArrayList.stream().collect(Collectors.joining(", ")); // "apple, bread, milk"

// for arrays

String[] shoppingArray = new String[]{"apple", "bread", "milk"};
String shoppingList4 = Arrays.stream(shoppingArray).collect(Collectors.joining(", ")); // "apple, bread, milk"
```

## Split String

### Into array

Using **.split(String delimiter)** method:

```java
String[] shoppingListSplitted = shoppingList.split(", "); // ["apple", "bread", "milk"]
```

Using **Pattern** (from Java 11):

```java
import java.util.regex.Pattern;

String[] shoppingListSplitted2 = Pattern.compile(", ")
        .splitAsStream(shoppingList)
        .toArray(String[]::new); // without argument, toArray() returns Object[] which cannot be casted to String[]
```

### Into List

Using **Pattern** (from Java 8):

```java
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

List<String> shoppingListSplitted3 = Pattern.compile(", ")
        .splitAsStream(shoppingList)
        .collect(Collectors.toList());
```

### Into Set

Using **Pattern** (from Java 8):

```java
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Set<String> shoppingListSplitted4 = Pattern.compile(", ")
        .splitAsStream(shoppingList)
        .collect(Collectors.toSet());
```

## Convert String into char array

Using **.toCharArray()** method:

```java
char[] nameLetters = name.toCharArray(); // ['F', 'o', 's', 's', 'e', 'r', 'y']
```
