2016-08-09 13 views
2

Ich habe Fragen zu SO zu erklären, dass Java automatisch Praktikanten String Literale und offensichtlich Praktikanten, wenn intern() aufgerufen wird. Ich frage mich jedoch, ob in einer Schleife (eine foreach Schleife in meinem Fall) die Strings auch automatisch interniert werden. Ich frage, weil ich Strings interniere, um Speicher in mehreren sehr großen LinkedHashMaps zu speichern und zu wissen, ob der Aufruf intern() redundant ist.Ist Java intern Strings in einer for-each-Schleife

Beispiel:

String array[] = createLargeArbitraryArray(); 
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length); 
for (String s : array) 
    map.put(s, 1f); 
} 

wäre das nächste Beispiel hat einen Unterschied in der Speichernutzung, als die ersten (unter der Annahme derselben array Werte) oder wird s bereits an diesem Punkt interniert?

String array[] = createLargeArbitraryArray(); 
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length); 
for (String s : array) 
    map.put(s.intern(), 1f); 
} 

Mir ist klar, dass in diesem Fall kann es keine gleichwertigen Strings sein, aber in meinem Fall habe ich einen benutzerdefinierten Schlüssel für mehrere Karten, die am Ende doppelte String-Werte nicht verwendet, und ich frage mich, ob intern() Aufruf um Speicher zu sparen, wäre an dieser Stelle überflüssig oder nicht.

Um zu dieser Frage hinzuzufügen, wenn ein Array aus Literalen erstellt wurde (in diesem Fall sind sie zunächst interniert), dann an eine Methode als Argument übergeben, würde eine Schleife wie oben internierte Strings verwenden oder nicht? d.h .:

/** 
* @param array created from literals 
*/ 
public void populateMap(String[] array) { 
    for (String s : array) 
    map.put(s, 1f); // Interned or not? 
} 

In diesem Fall entweder s wird interniert, weil array zu beginnen wurde interniert oder s ist interniert nicht, weil es als ein neues Objekt in der Schleife Parameter deklariert wird. Welches ist richtig?

EDIT: Um meine Gründe für das Internieren weiter zu erklären, möchte ich Speicher im Heap freigeben, um zu vermeiden, die maximale Heap-Größe oder GC-Overhead-Grenze zu treffen. Leistung und Geschwindigkeit sind nicht extrem wichtig für mich in diesem Fall.

+1

Hmm ... Ich bin skeptisch, wenn es darum geht, Saiten selbst zu "internieren". Haben Sie einen tatsächlichen Leistungsvorteil gemessen? Oft kann es sogar die Leistung beeinträchtigen. –

+0

habe ich noch nicht. Ich bin bereit, etwas Leistung/Geschwindigkeit zu opfern, um zu vermeiden, Heap- oder GC-Overhead-Grenzen zu treffen. Mein Hauptgrund für das Praktikum ist das Gedächtnis, nicht die Leistung. – 17slim

+0

Dann nehme ich an, dass in diesem Fall, wenn Sie wollten, dass Ihre Strings interniert werden, dann sollten Sie es explizit nennen. Sie werden nicht automatisch interniert. –

Antwort

2

Explizit Aufruf intern() ist der richtige Ansatz hier (oder wie PC luddite sagt, ob Sie wirklich interning benötigen). Ich kenne keine JIT-Compiler in der JVM, die das tun (selbst wenn es eine Optimierung gibt, die das tut, sollten Sie sich nicht darauf verlassen).

Wenn ein Array aus intern gespeicherten Strings erstellt und dann an eine Methode übergeben und dann verwendet wird, werden die internierten Strings verwendet. Es werden keine zusätzlichen Zeichenfolgen erstellt.

+0

Danke für die Antwort!Ich habe eine letzte Frage: Sagen wir, ich setze ein zweites Array auf ein internes Array ('array2 = internedArray'), würde' array2' dann die gleichen internierten String-Objekte enthalten? – 17slim

+1

@ 17slim - Ja. Beide Arrays enthalten Verweise auf dieselben String-Literale (im String-Konstanten-Pool). Denken Sie daran, dass Java ein pass by value ist (selbst Referenzen werden als Wert übergeben). Wenn Sie den Array-Verweis an andere Methoden übergeben, werden die gleichen String-Literale wiederverwendet. – TheLostMind

+0

JVMs können kein beliebiges automatisches Interning ausführen, da dies die Semantik von Programm, wenn zwei explizit erstellte String-Instanzen plötzlich dieselbe Instanz sind. Oder, wenn die JVM beweisen kann, dass die gesamte Anwendung diese Änderung der Objektidentitäten niemals bemerken wird, wäre es möglich, aber ich behaupte, dass die Durchführung solcher Beweise die Vorteile überwiegen würde. Die kürzlichen JVMs können die internen Array-Referenzen ändern, so dass bestimmte String-Instanzen mit gleichen Inhalten gezwungen sind, dieselbe Array-Instanz zu verwenden. – Holger