Sök…


Introduktion

Strängar ( java.lang.String ) är java.lang.String lagras i ditt program. Strängar är inte en primitiv datatyp i Java , men de är mycket vanliga i Java-program.

I Java är strängar obrukbara, vilket betyder att de inte kan ändras. (Klicka här för en mer grundlig förklaring av immutability.)

Anmärkningar

Eftersom Java-strängar är oföränderliga kommer alla metoder som manipulerar en String att returnera ett nytt String objekt . De ändrar inte den ursprungliga String . Detta inkluderar att ersätta och ersätta metoder som C- och C ++ -programmerare förväntar sig att mutera målet String objekt.


Använd en StringBuilder istället för String om du vill sammanfoga fler än två String vars värden inte kan bestämmas vid sammanställningstiden. Den här tekniken är mer performant än att skapa nya String objekt och sammanfoga dem eftersom StringBuilder är muterbar.

StringBuffer kan också användas för att sammanfoga String . Men den här klassen är mindre prestanda eftersom den är utformad för att vara trådsäker och får en mutex före varje operation. Eftersom du nästan aldrig behöver trådsäkerhet när du kopplar samman strängar är det bäst att använda StringBuilder .

Om du kan uttrycka en strängkoppling som ett enda uttryck, är det bättre att använda + -operatören. Java-kompilatorn konverterar ett uttryck som innehåller + sammanlänkningar till en effektiv sekvens av operationer med antingen String.concat(...) eller StringBuilder . StringBuilder att använda StringBuilder uttryckligen endast när sammankopplingen innebär flera uttryck.


Förvara inte känslig information i strängar. Om någon har möjlighet att få en minnesdump av ditt körande program kan de hitta alla befintliga String och läsa innehållet. Detta inkluderar String som inte kan nås och väntar på skräppost. Om detta är ett problem måste du torka känsliga strängdata så snart du är klar med det. Du kan inte göra detta med String objekt eftersom de är oföränderliga. Därför är det tillrådligt att använda ett char[] -objekt för att hålla känslig teckeninformation och torka av dem (t.ex. skriva över dem med '\000' tecken) när du är klar.


Alla String skapas på högen, även fall som motsvarar strängbokstäver. Det speciella med strängbokstäver är att JVM ser till att alla bokstäver som är lika (dvs. som består av samma tecken) representeras av ett enda String (detta beteende specificeras i JLS). Detta implementeras av JVM-klasslastare. När en klasslastare laddar en klass söker den efter strängbokstäver som används i klassdefinitionen, varje gång den ser en kontrollerar den om det redan finns en post i strängpoolen för denna bokstav (använder bokstaven som nyckel) . Om det redan finns en post för det bokstavliga används referensen till en String lagrad som paret för den bokstavliga. Annars skapas en ny String instans och en referens till instansen lagras för det bokstavliga (används som en nyckel) i strängpoolen. (Se även stränginterning ).

Strängpoolen hålls i Java-högen och omfattas av normal skräppassning.

Java SE 7

I utgivningar av Java före Java 7 hölls strängpoolen i en speciell del av högen känd som "PermGen". Denna del samlades bara ibland.

Java SE 7

I Java 7 flyttades strängpoolen från "PermGen".

Observera att strängbokstäver implicit kan nås från alla metoder som använder dem. Detta innebär att motsvarande String objekt endast kan samlas in om koden i sig är skräp som samlas in.


Fram till Java 8, String är föremål implementeras som en UTF-16 char array (2 bytes per char). Det finns ett förslag i Java 9 att implementera String som en byte-matris med ett kodningsflaggfält för att notera om strängen är kodad som byte (LATIN-1) eller chars (UTF-16).

Jämför strängar

För att jämföra Strängar för jämlikhet bör du använda String-objektets equals eller equalsIgnoreCase metoder.

Till exempel kommer följande utdrag att avgöra om de två instanserna av String är lika på alla tecken:

String firstString = "Test123";
String secondString = "Test" + 123;

if (firstString.equals(secondString)) {
   // Both Strings have the same content.
}

Live-demo

Detta exempel kommer att jämföra dem, oberoende av deras fall:

String firstString = "Test123";
String secondString = "TEST123";

if (firstString.equalsIgnoreCase(secondString)) {
    // Both Strings are equal, ignoring the case of the individual characters.
}

Live-demo

Observera att equalsIgnoreCase inte låter dig ange ett Locale . Om du till exempel jämför de två orden "Taki" och "TAKI" på engelska är de lika; på turkiska är de emellertid olika (på turkiska är gemener I ı ). För fall som detta är lösningen att konvertera båda strängarna till små (eller versaler) med Locale och sedan jämföra med equals .

String firstString = "Taki";
String secondString = "TAKI";

System.out.println(firstString.equalsIgnoreCase(secondString)); //prints true

Locale locale = Locale.forLanguageTag("tr-TR");

System.out.println(firstString.toLowerCase(locale).equals(
                   secondString.toLowerCase(locale))); //prints false

Live-demo


Använd inte operatören == för att jämföra strängar

Om du inte kan garantera att alla strängar har internerats (se nedan), bör du inte använda operatörerna == eller != För att jämföra strängar. Dessa operatörer testar faktiskt referenser, och eftersom flera String kan representera samma sträng kan detta ge fel svar.

String.equals(Object) metoden String.equals(Object) , som kommer att jämföra strängobjekten baserat på deras värden. För en detaljerad förklaring, se Pitfall: använda == för att jämföra strängar .


Jämför strängar i ett switch-uttalande

Java SE 7

Från Java 1.7 är det möjligt att jämföra en strängvariabel med bokstavar i en switch sats. Se till att strängen inte är noll, annars kommer den alltid att kasta en NullPointerException . Värden jämförs med String.equals , dvs skiftlägeskänsliga.

String stringToSwitch = "A";

switch (stringToSwitch) {
    case "a":
        System.out.println("a");
        break;
    case "A":
        System.out.println("A"); //the code goes here
        break;
    case "B":
        System.out.println("B");
        break;
    default:
        break;
}

Live-demo

Jämförelse av strängar med konstanta värden

När du jämför en String med ett konstant värde kan du placera konstantvärdet på vänster sida av equals att säkerställa att du inte får en NullPointerException om den andra strängen är null .

"baz".equals(foo)

Medan foo.equals("baz") kommer att kasta en NullPointerException om foo är null , kommer "baz".equals(foo) att utvärderas till false .

Java SE 7

Ett mer läsbart alternativ är att använda Objects.equals() , som gör en nollkontroll av båda parametrarna: Objects.equals(foo, "baz") .

( Obs: Det kan diskuteras om det är bättre att undvika NullPointerExceptions i allmänhet, eller låta dem hända och sedan fixa grundorsaken; se här och här . Det är givetvis inte att motivera att undvika strategin "bästa praxis".)

Strängbeställningar

String klassen implementerar Comparable<String> med String.compareTo metoden (som beskrivs i början av detta exempel). Detta gör den naturliga beställningen av String objekt skiftlägeskänslig ordning. String klassen ger en Comparator<String> CASE_INSENSITIVE_ORDER heter CASE_INSENSITIVE_ORDER lämplig för kassalysensitiv sortering.

Jämförelse med internerade strängar

Java Language Specification ( JLS 3.10.6 ) anger följande:

"Dessutom hänvisar en strängbokstavs alltid till samma instans av String . Detta beror på att strängbokstäver - eller mer generellt strängar som är värdena för konstant uttryck - interneras så att de delar unika instanser med hjälp av metoden String.intern . "

Detta betyder att det är säkert att jämföra referenser till två strängbokstäver med == . Detsamma gäller för referenser till String objekt som har producerats med String.intern() .

Till exempel:

String strObj = new String("Hello!");
String str = "Hello!";

// The two string references point two strings that are equal
if (strObj.equals(str)) {
    System.out.println("The strings are equal");
}

// The two string references do not point to the same object
if (strObj != str) {
    System.out.println("The strings are not the same object");
}

// If we intern a string that is equal to a given literal, the result is
// a string that has the same reference as the literal.
String internedStr = strObj.intern();

if (internedStr == str) {
    System.out.println("The interned string and the literal are the same object");
}

Bakom kulisserna har interningmekanismen ett hashbord som innehåller alla internade strängar som fortfarande är tillgängliga . När du ringer intern() på en String , söker metoden upp objektet i hashtabellen:

  • Om strängen hittas, returneras det värdet som den internerade strängen.
  • Annars läggs en kopia av strängen till hashtabellen och den strängen returneras som den internerade strängen.

Det är möjligt att använda interning för att göra det möjligt att jämföra strängar med == . Men det finns betydande problem med att göra detta; se Pitfall - Interning strängar så att du kan använda == är en dålig idé för detaljer. Det rekommenderas inte i de flesta fall.

Ändra fallet med tecken i en sträng

String ger två metoder för att konvertera strängar mellan versaler och gemener:

  • toUpperCase att konvertera alla tecken till versaler
  • toLowerCase att konvertera alla tecken till små bokstäver

Dessa metoder returnerar båda de konverterade strängarna som nya String instanser: de ursprungliga String objekten ändras inte eftersom String är oföränderlig i Java. Se detta för mer om immutability: Immutability of Strings in Java

String string = "This is a Random String";
String upper = string.toUpperCase();
String lower = string.toLowerCase();

System.out.println(string);   // prints "This is a Random String"
System.out.println(lower);    // prints "this is a random string"
System.out.println(upper);    // prints "THIS IS A RANDOM STRING"

Icke-alfabetiska tecken, såsom siffror och skiljetecken, påverkas inte av dessa metoder. Observera att dessa metoder också på vissa sätt kan hantera vissa Unicode-tecken på fel sätt.


Obs : Dessa metoder är landskänsliga och kan ge oväntade resultat om de används på strängar som är tänkta att tolkas oberoende av landskapet. Exempel är programmeringsspråkidentifierare, protokollnycklar och HTML taggar.

Till exempel "TITLE".toLowerCase() i ett turkiskt språk " tıtle ", där ı (\u0131) är LATIN SMALL LETTER DOTLESS I- tecknet. För att få korrekta resultat för lokala känsliga strängar, Locale.ROOT som en parameter till motsvarande toLowerCase(Locale.ROOT) t.ex. toLowerCase(Locale.ROOT) eller toUpperCase(Locale.ROOT) ).

Även om användning av Locale.ENGLISH är korrekt i de flesta fall, är det språkvariant sättet Locale.ROOT .

En detaljerad lista med Unicode-tecken som kräver speciellt hölje finns på Unicode Consortiums webbplats .

Ändra fall av ett specifikt tecken i en ASCII-sträng:

För att ändra fallet med ett specifikt tecken i en ASCII-sträng kan följande algoritm användas:

Steg:

  1. Förklara en sträng.
  2. Mata in strängen.
  3. Konvertera strängen till en teckenuppsättning.
  4. Ange det tecken som ska sökas.
  5. Sök efter karaktären i teckenfältet.
  6. Om det hittas, kontrollera om tecknen är små eller stora versaler.
    • Lägg till 32 till ASCII-koden för tecknet om versaler.
    • Om små bokstäver, subtrahera 32 från teckens ASCII-kod.
  7. Ändra det ursprungliga tecknet från teckenfältet.
  8. Konvertera teckenfältet tillbaka till strängen.

Voila, karaktärens fall ändras.

Ett exempel på koden för algoritmen är:

Scanner scanner = new Scanner(System.in);
System.out.println("Enter the String");
String s = scanner.next();
char[] a = s.toCharArray();
System.out.println("Enter the character you are looking for");
System.out.println(s);
String c = scanner.next();
char d = c.charAt(0);

for (int i = 0; i <= s.length(); i++) {
    if (a[i] == d) {
        if (d >= 'a' && d <= 'z') {
            d -= 32;
        } else if (d >= 'A' && d <= 'Z') {
            d += 32;
        }
        a[i] = d;
        break;
    }
}
s = String.valueOf(a);
System.out.println(s);

Hitta en sträng inom en annan sträng

För att kontrollera om en viss sträng a finns i en sträng b eller inte, kan vi använda metoden String.contains() med följande syntax:

b.contains(a); // Return true if a is contained in b, false otherwise

String.contains() kan användas för att verifiera om en CharSequence kan hittas i strängen. Metoden letar efter strängen a i strängen b på ett skiftlägeskänsligt sätt.

String str1 = "Hello World";
String str2 = "Hello";
String str3 = "helLO";

System.out.println(str1.contains(str2)); //prints true
System.out.println(str1.contains(str3)); //prints false

Live Demo på Ideone


För att hitta den exakta positionen där en sträng startar inom en annan sträng använder du String.indexOf() :

String s = "this is a long sentence";
int i = s.indexOf('i');    // the first 'i' in String is at index 2
int j = s.indexOf("long"); // the index of the first occurrence of "long" in s is 10
int k = s.indexOf('z');    // k is -1 because 'z' was not found in String s
int h = s.indexOf("LoNg"); // h is -1 because "LoNg" was not found in String s

Live Demo på Ideone

String.indexOf() returnerar det första indexet för en char eller String i en annan String . Metoden returnerar -1 om den inte hittas.

Obs : String.indexOf() -metoden är skiftlägeskänslig.

Exempel på sökning som ignorerar ärendet:

String str1 = "Hello World";
String str2 = "wOr";
str1.indexOf(str2);                               // -1
str1.toLowerCase().contains(str2.toLowerCase());  // true
str1.toLowerCase().indexOf(str2.toLowerCase());   // 6

Live Demo på Ideone

Få längden på en sträng

För att få längden på ett String , ring length() -metoden på det. Längden är lika med antalet UTF-16-kodenheter (tecken) i strängen.

String str = "Hello, World!";
System.out.println(str.length()); // Prints out 13

Live Demo på Ideone

En char i en sträng är UTF-16-värdet. Unicode-kodpunkterna vars värden är ≥ 0x1000 (till exempel de flesta emojis) använder två char-positioner. För att räkna antalet Unicode-kodpunkter i en sträng, oavsett om varje kodpunkt passar i ett UTF-16- char , kan du använda metoden codePointCount :

int length = str.codePointCount(0, str.length());

Du kan också använda en ström av codepoints, från Java 8:

int length = str.codePoints().count();

delsträngar

String s = "this is an example";
String a = s.substring(11); // a will hold the string starting at character 11 until the end ("example")
String b = s.substring(5, 10); // b will hold the string starting at character 5 and ending right before character 10 ("is an")
String b = s.substring(5, b.length()-3); // b will hold the string starting at character 5 ending right before b' s lenght is out of 3  ("is an exam")

Underlag kan också appliceras på skivan och lägga till / ersätta tecken i dess ursprungliga sträng. Till exempel mötte du ett kinesiskt datum som innehåller kinesiska tecken men du vill lagra det som ett brunnformatdatasträng.

String datestring = "2015年11月17日"
datestring = datestring.substring(0, 4) + "-" + datestring.substring(5,7) + "-" + datestring.substring(8,10);
//Result will be 2015-11-17

Substringsmetoden extraherar en bit av en String . När den tillhandahålls en parameter är parametern start och stycket sträcker sig till String . När två parametrar ges är den första parametern starttecknet och den andra parametern är teckens index direkt efter slutet (tecknet vid indexet ingår inte). Ett enkelt sätt att kontrollera är subtraktionen av den första parametern från den andra bör ge den förväntade längden på strängen.

Java SE 7

I JDK <7u6-versioner substring substringmetoden en String som delar samma char[] som den ursprungliga String och har de interna offset och count inställda på resultatets start och längd. Sådan delning kan orsaka minnesläckor, som kan förhindras genom att anropa new String(s.substring(...)) att tvinga skapandet av en kopia, varefter char[] kan samlas in.

Java SE 7

Från JDK 7u6 substring alltid substringmetoden hela underliggande char[] -fältet, vilket gör komplexiteten linjär jämfört med den föregående konstanten men garanterar frånvaron av minnesläckor på samma gång.

Få den nionde karaktären i en sträng

String str = "My String";

System.out.println(str.charAt(0)); // "M"
System.out.println(str.charAt(1)); // "y"
System.out.println(str.charAt(2)); // " "
System.out.println(str.charAt(str.length-1)); // Last character "g"

För att få det nionde tecknet i en sträng, ring bara charAt(n) på en String , där n är indexet för det tecken du vill hämta

OBS: index n börjar vid 0 , så det första elementet är på n = 0.

Plattformoberoende ny linjeseparator

Eftersom den nya linjeseparatorn varierar från plattform till plattform (t.ex. \n på Unix-liknande system eller \r\n på Windows) är det ofta nödvändigt att ha ett plattformsoberoende sätt att komma åt den. I Java kan det hämtas från en systemegenskap:

System.getProperty("line.separator")
Java SE 7

Eftersom den nya linjeseparatorn är så vanligt behövs, från Java 7 på en genvägsmetod som returnerar exakt samma resultat som koden ovan:

System.lineSeparator()

Obs : Eftersom det är mycket osannolikt att den nya linjeseparatorn ändras under programmets körning är det en bra idé att lagra den i en statisk slutvariabel istället för att hämta den från systemegenskapen varje gång den behövs.

När du använder String.format , använd %n snarare än \n eller '\ r \ n' för att mata ut en plattformsoberoende ny radseparator.

System.out.println(String.format('line 1: %s.%nline 2: %s%n', lines[0],lines[1]));

Lägga till metoden String () för anpassade objekt

Anta att du har definierat följande Person :

public class Person {

    String name;
    int age;
    
    public Person (int age, String name) {
        this.age = age;
        this.name = name;
    }
}

Om du instanserar ett nytt Person objekt:

Person person = new Person(25, "John");

och senare i din kod använder du följande uttalande för att skriva ut objektet:

System.out.println(person.toString());

Live Demo på Ideone

får du en utgång som liknar följande:

Person@7ab89d

Detta är resultatet av implementeringen av toString() -metoden definierad i Object , en superklass av Person . Dokumentationen för Object.toString() anger:

Metoden toString för klassobjekt returnerar en sträng som består av namnet på den klass som objektet är en instans, at-sign-karaktären `@ 'och den osignerade hexadecimala representationen av hashkoden för objektet. Med andra ord returnerar denna metod en sträng som är lika med värdet på:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Så för meningsfull produktion måste du åsidosätta toString() :

@Override
public String toString() {
    return "My name is " + this.name + " and my age is " + this.age;
}

Nu kommer utgången att vara:

My name is John and my age is 25

Du kan också skriva

System.out.println(person);

Live Demo på Ideone

I själva verket åberopar println() implicit toString metoden på objektet.

Splitssträngar

Du kan dela en String på ett visst avgränsande tecken eller ett regelbundet uttryck , du kan använda String.split() som har följande signatur:

public String[] split(String regex)

Observera att avgränsning av tecken eller reguljärt uttryck tas bort från den resulterande strängarrayen.

Exempel med avgränsande karaktär:

String lineFromCsvFile = "Mickey;Bolton;12345;121216";
String[] dataCells = lineFromCsvFile.split(";");
// Result is dataCells = { "Mickey", "Bolton", "12345", "121216"};

Exempel med regelbundet uttryck:

String lineFromInput = "What    do you need    from me?";
String[] words = lineFromInput.split("\\s+"); // one or more space chars
// Result is words = {"What", "do", "you", "need", "from", "me?"};

Du kan till och med direkt dela en String bokstav:

String[] firstNames = "Mickey, Frank, Alicia, Tom".split(", ");
// Result is firstNames = {"Mickey", "Frank", "Alicia", "Tom"};

Varning : Glöm inte att parametern alltid behandlas som ett vanligt uttryck.

"aaa.bbb".split("."); // This returns an empty array

I föregående exempel . behandlas som det vanliga uttrycket jokertecken som matchar alla tecken, och eftersom varje tecken är en avgränsare är resultatet en tom matris.


Delning baserad på en avgränsare som är en regex-metatecken

Följande tecken betraktas som speciella (aka metatecken) i regex

  < > - = ! ( ) [ ] { } \ ^ $ | ? * + . 

För att dela en sträng baserad på en av ovanstående avgränsare, måste du antingen undvika dem med \\ eller använda Pattern.quote() :

  • Använda Pattern.quote() :

     String s = "a|b|c";
     String regex = Pattern.quote("|");
     String[] arr = s.split(regex);
    
  • Undvika specialtecken:

     String s = "a|b|c";
     String[] arr = s.split("\\|");
    

Delning tar bort tomma värden

split(delimiter) tar som standard bort släpning av tomma strängar från resultatuppsättningen. För att stänga av denna mekanism måste vi använda överbelastad version av split(delimiter, limit) med gränsen inställd på negativt värde som

String[] split = data.split("\\|", -1);

split(regex) returnerar internt resultatet av split(regex, 0) .

Gränsparametern styr antalet gånger mönstret appliceras och påverkar därför längden på den resulterande matrisen.
Om gränsen n är större än noll kommer mönstret att tillämpas högst n - 1 gånger, matrisens längd blir inte större än n , och matrisens sista post kommer att innehålla alla inmatningar utöver den sista matchade avgränsaren.
Om n är negativt kommer mönstret att appliceras så många gånger som möjligt och matrisen kan ha valfri längd.
Om n är noll kommer mönstret att appliceras så många gånger som möjligt, matrisen kan ha vilken längd som helst och släpning av tomma strängar kommer att kasseras.


Dela med en StringTokenizer

Förutom split() -metoden kan Strings också delas med hjälp av en StringTokenizer .

StringTokenizer är ännu mer restriktivt än String.split() , och också lite svårare att använda. Det är i huvudsak utformat för att dra ut tokens avgränsade av en fast uppsättning tecken (ges som en String ). Varje tecken kommer att fungera som en separator. På grund av denna begränsning är det ungefär dubbelt så snabbt som String.split() .

Standarduppsättning tecken är tomma mellanslag ( \t\n\r\f ). Följande exempel kommer att skriva ut varje ord separat.

String str = "the lazy fox jumped over the brown fence";
StringTokenizer tokenizer = new StringTokenizer(str);
while (tokenizer.hasMoreTokens()) {
    System.out.println(tokenizer.nextToken());
}

Detta kommer att skriva ut:

the
lazy 
fox 
jumped 
over 
the 
brown 
fence

Du kan använda olika teckenuppsättningar för separering.

String str = "jumped over";
// In this case character `u` and `e` will be used as delimiters 
StringTokenizer tokenizer = new StringTokenizer(str, "ue");
while (tokenizer.hasMoreTokens()) {
    System.out.println(tokenizer.nextToken());
}

Detta kommer att skriva ut:

j
mp 
d ov
r

Gå med strängar med en avgränsare

Java SE 8

En rad strängar kan förenas med den statiska metoden String.join() :

String[] elements = { "foo", "bar", "foobar" };
String singleString = String.join(" + ", elements);

System.out.println(singleString); // Prints "foo + bar + foobar"     

På liknande sätt finns det en överbelastad String.join() -metod för Iterable s.


För att ha en finkornig kontroll över sammanfogningen kan du använda StringJoiner- klassen:

StringJoiner sj = new StringJoiner(", ", "[", "]"); 
    // The last two arguments are optional, 
    // they define prefix and suffix for the result string

sj.add("foo");
sj.add("bar");
sj.add("foobar");

System.out.println(sj); // Prints "[foo, bar, foobar]"

För att gå med i en ström av strängar kan du använda sammankopplingssamlaren :

Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", "));
System.out.println(joined); // Prints "foo, bar, foobar"

Det finns ett alternativ att definiera prefix och suffix här också:

Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", ", "{", "}"));
System.out.println(joined); // Prints "{foo, bar, foobar}"

Reversing Strings

Det finns ett par sätt att vända en sträng för att göra den bakåt.

  1. String / String:

     String code = "code";
     System.out.println(code);
    
     StringBuilder sb = new StringBuilder(code); 
     code = sb.reverse().toString();
    
     System.out.println(code);
    
  2. Char array:

    String code = "code";
    System.out.println(code);
    
    char[] array = code.toCharArray();
    for (int index = 0, mirroredIndex = array.length - 1; index < mirroredIndex; index++, mirroredIndex--) {
        char temp = array[index];
        array[index] = array[mirroredIndex];
        array[mirroredIndex] = temp;
    }
    
    // print reversed
    System.out.println(new String(array));
    

Räkna förekomster av en substring eller tecken i en sträng

countMatches metoden från org.apache.commons.lang3.StringUtils används vanligtvis för att räkna förekomster av en substring eller tecken i en String :

import org.apache.commons.lang3.StringUtils;

String text = "One fish, two fish, red fish, blue fish";

// count occurrences of a substring
String stringTarget = "fish";
int stringOccurrences = StringUtils.countMatches(text, stringTarget); // 4

// count occurrences of a char
char charTarget = ',';
int charOccurrences = StringUtils.countMatches(text, charTarget); // 3

Annars för gör samma sak med vanliga Java API: er kan du använda Regular Expressions:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
String text = "One fish, two fish, red fish, blue fish";
System.out.println(countStringInString("fish", text)); // prints 4
System.out.println(countStringInString(",", text)); // prints 3
 

public static int countStringInString(String search, String text) {
    Pattern pattern = Pattern.compile(search);
    Matcher matcher = pattern.matcher(text);
    
    int stringOccurrences = 0;
    while (matcher.find()) {
      stringOccurrences++;
    }
    return stringOccurrences;
}

Strängen sammankoppling och StringBuilders

Strängen sammanlänkning kan utföras med hjälp av + operatören. Till exempel:

String s1 = "a";
String s2 = "b";
String s3 = "c";
String s = s1 + s2 + s3; // abc

Normalt utför en kompilatorimplementering ovanstående sammanlänkning med metoder som involverar en StringBuilder under huven. Vid sammanställning skulle koden se ut som nedan:

StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append("c").toString();

StringBuilder har flera överbelastade metoder för att lägga till olika typer, till exempel att lägga till en int istället för en String . Till exempel kan en implementering konvertera:

String s1 = "a";
String s2 = "b";    
String s = s1 + s2 + 2; // ab2

till det följande:

StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append(2).toString();

Ovanstående exempel illustrerar en enkel sammankopplingsoperation som effektivt utförs på en enda plats i koden. Samkopplingen involverar en enda instans av StringBuilder . I vissa fall utförs en sammankoppling på ett kumulativt sätt, t.ex. i en slinga:

String result = "";
for(int i = 0; i < array.length; i++) {
    result += extractElement(array[i]);
}
return result;

I sådana fall tillämpas vanligtvis inte kompilatoroptimeringen, och varje iteration skapar ett nytt StringBuilder objekt. Detta kan optimeras genom att uttryckligen omvandla koden till en enda StringBuilder :

StringBuilder result = new StringBuilder();
for(int i = 0; i < array.length; i++) {
    result.append(extractElement(array[i]));
}
return result.toString();

En StringBuilder kommer att initialiseras med ett tomt utrymme på endast 16 tecken. Om du i förväg vet att du kommer att bygga större strängar kan det vara fördelaktigt att initiera den med tillräcklig storlek i förväg, så att den interna bufferten inte behöver ändras i storlek:

StringBuilder buf = new StringBuilder(30); // Default is 16 characters
buf.append("0123456789");
buf.append("0123456789"); // Would cause a reallocation of the internal buffer otherwise
String result = buf.toString(); // Produces a 20-chars copy of the string

Om du producerar många strängar rekommenderas att återanvända StringBuilder s:

StringBuilder buf = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
    buf.setLength(0); // Empty buffer
    buf.append("This is line ").append(i).append('\n');
    outputfile.write(buf.toString());
}

Om (och bara om) flera trådar skriver till samma buffert använder du StringBuffer , som är en synchronized version av StringBuilder . Men eftersom vanligtvis bara en enda tråd skriver till en buffert är det vanligtvis snabbare att använda StringBuilder utan synkronisering.

Med hjälp av concat () -metoden:

String string1 = "Hello ";
String string2 = "world";
String string3 = string1.concat(string2);  // "Hello world"

Detta returnerar en ny sträng som är sträng1 med sträng2 läggs till i slutet. Du kan också använda concat () -metoden med strängbokstäver, som i:

"My name is ".concat("Buyya");

Byta ut delar av strängar

Två sätt att ersätta: med regex eller exakt matchning.

Obs: det ursprungliga String-objektet kommer att vara oförändrat, returvärdet har den ändrade strängen.

Exakt matchning

Ersätt enstaka tecken med en annan enstaka tecken:

String replace(char oldChar, char newChar) 

Returnerar en ny sträng som kommer från att ersätta alla förekomster av oldChar i den här strängen med newChar.

String s = "popcorn";
System.out.println(s.replace('p','W'));

Resultat:

WoWcorn

Ersätt teckenföljd med en annan teckenföljd:

String replace(CharSequence target, CharSequence replacement) 

Ersätter varje substring i den här strängen som matchar den bokstavliga målsekvensen med den angivna bokstavliga ersättningssekvensen.

String s = "metal petal et al.";
System.out.println(s.replace("etal","etallica"));

Resultat:

metallica petallica et al.

regex

Obs : grupperingarna använder tecknet $ att referera till grupperna, till exempel $1 .

Byt ut alla matchningar:

String replaceAll(String regex, String replacement) 

Ersätter varje substring i den här strängen som matchar det givna regelbundna uttrycket med den givna ersättningen.

String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));

Resultat:

spiral metallica petallica et al.

Ersätt endast första matchen:

String replaceFirst(String regex, String replacement) 

Ersätter den första substansen i den här strängen som matchar det givna regelbundna uttrycket med den givna ersättaren

String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));

Resultat:

spiral metallica petal et al.

Ta bort Whitespace från början och slut på en sträng

Metoden trim() returnerar en ny sträng med det ledande och efterföljande vitrummet borttaget.

String s = new String("   Hello World!!  ");
String t = s.trim();  // t = "Hello World!!"

Om du trim en sträng som inte har något utrymme att ta bort kommer du tillbaka samma String-instans.

Observera att trim() har sin egen uppfattning om whitespace , vilket skiljer sig från begreppet som används av Character.isWhitespace() -metoden:

  • Alla ASCII-kontrolltecken med koderna U+0000 till U+0020 betraktas som mellanrum och tas bort med trim() . Detta inkluderar U+0020 'SPACE' , U+0009 'CHARACTER TABULATION' , U+000A 'LINE FEED' och U+000D 'CARRIAGE RETURN' tecken, men också karaktärerna som U+0007 'BELL' .

  • Unicode-blanksteg som U+00A0 'NO-BREAK SPACE' eller U+2003 'EM SPACE' känns inte igen av trim() .

Strängpool och höglagring

Liksom många Java-objekt skapas alla String instanser på högen, till och med bokstäver. När JVM hittar en String bokstav som inte har någon motsvarande referens i högen, skapar JVM en motsvarande String instans på högen och den lagrar också en referens till den nyligen skapade String instansen i String-poolen. Alla andra referenser till samma String letteral ersätts med den tidigare skapade String instansen i högen.

Låt oss titta på följande exempel:

class Strings
{
    public static void main (String[] args)
    {
        String a = "alpha";
        String b = "alpha";
        String c = new String("alpha");

        //All three strings are equivalent
        System.out.println(a.equals(b) && b.equals(c));

        //Although only a and b reference the same heap object
        System.out.println(a == b);
        System.out.println(a != c);
        System.out.println(b != c);
    }
}

Utgången från ovanstående är:

true
true
true
true

Diagram över Java Heap and String pool När vi använder dubbla citat för att skapa en sträng, letar den först efter sträng med samma värde i strängpoolen, om den hittar den bara referensen, annars skapar den en ny sträng i poolen och returnerar sedan referensen.

Men med ny operatör tvingar vi String class att skapa ett nytt String-objekt i högutrymmet. Vi kan använda metoden intern () för att lägga den i poolen eller hänvisa till andra String-objekt från strängpool med samma värde.

Själva strängpoolen skapas också på högen.

Java SE 7

Före Java 7 String ades litteraler lagras i runtime konstant pool i metoden området PermGen , som hade en fast storlek.

Strängpoolen var också bosatt i PermGen .

Java SE 7

RFC: 6962931

I JDK 7 fördelas inte längre internerade strängar i den permanenta generationen av Java-högen, utan tilldelas istället i huvuddelen av Java-högen (känd som de unga och gamla generationerna), tillsammans med de andra föremål som skapats av applikationen . Denna förändring kommer att resultera i att mer data finns i den huvudsakliga Java-högen och mindre data i den permanenta generationen, och kan därför kräva att högstorlekar justeras. De flesta applikationer ser bara relativt små skillnader i heapanvändning på grund av denna förändring, men större applikationer som laddar många klasser eller använder tungt med String.intern() -metoden kommer att se mer betydande skillnader.

Ärende känslig switch

Java SE 7

switch kan inte parametreras för att vara känslig för versaler, men om absolut krävs kan den uppträda okänslig för ingångssträngen med toLowerCase() eller toUpperCase :

switch (myString.toLowerCase()) {
     case "case1" :
        ...            
     break;
     case "case2" :
        ...            
     break;
}

Akta sig

  • Locale kan påverka hur förändrade fall händer !
  • Man måste vara försiktig så att inga stora bokstäver finns i etiketterna - de kommer aldrig att köras!


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow