Подсчет объектов String, созданных кодом Java

Увидев, что это довольно популярный вопрос - ответ ДА.

Для столбца column в таблице table, содержащего все ваши данные, разделенные комой:

CREATE TEMPORARY TABLE temp (val CHAR(255));
SET @S1 = CONCAT("INSERT INTO temp (val) VALUES ('",REPLACE((SELECT GROUP_CONCAT( DISTINCT  `column`) AS data FROM `table`), ",", "'),('"),"');");
PREPARE stmt1 FROM @s1;
EXECUTE stmt1;
SELECT DISTINCT(val) FROM temp;
< hr>

Пожалуйста, помните, однако, чтобы не хранить CSV в вашей БД


Per @Mark Amery - так как это переводит значения, разделенные комой, в инструкцию INSERT, будьте осторожны при запуске ее на неанитированной data


Просто повторите, пожалуйста, не храните CSV в своей БД; эта функция предназначена для преобразования CSV в разумную структуру БД и не использоваться в любом месте вашего кода. Если вам нужно использовать его в производстве, переосмыслите структуру своего БД

23
задан dasblinkenlight 22 April 2015 в 12:57
поделиться

13 ответов

К концу цикла будет четыре String объекта:

  1. A String, который соответствует интернированному "xyz" литералу
  2. Его копия создана new String("xyz")
  3. String, что соответствует интернированному "abc" литералу
  4. A String, что соответствует конкатенации "xyz" + "abc"

Реальное Вопрос в приписывает некоторые или все эти объекты вашей программе. Можно с полным основанием утверждать, что в вашем коде создано от двух до четырех String. Даже если всего имеется четыре String объекта, объекты 1 и 3 могут не обязательно создаваться вашим кодом, потому что они находятся в постоянном пуле, поэтому они создаются вне прямого контроля вашего кода.

49
ответ дан dasblinkenlight 22 April 2015 в 12:57
поделиться

Этот ответ предназначен для исправления неправильного представления, которое возникает у некоторых из других ответов:

Например:

Компилятор может заменить x + y константой ("xyzabc"), хотя. @Binkan Salaryman

... и объект String 4 [String, который соответствует конкатенации] может быть вычислен компилятором и также превращен в интернированную константу. @dasblinkenlight

Это неверно. JLS утверждает это:

15.18.1. Оператор конкатенации строк +

....

Объект String создается заново (§12.5), если выражение не является константным выражением (§15.28).

Чтобы квалифицироваться как постоянное выражение, имена переменных в выражении должны быть:

Простые имена (§6.5.6.1), которые ссылаются на постоянные переменные ( §4.12.4).

где «постоянная переменная» определяется как:

Постоянная переменная - это конечная переменная примитивного типа или типа String, которая инициализируется постоянным выражением (§ 15,28). [тысяча сто двадцать семь]

В этом примере ни x, ни y не являются final, поэтому они не являются постоянными переменными. И даже если бы они были final, y , все равно не были бы постоянной переменной из-за использования оператора new при его инициализации.


Короче говоря, компилятору Java не разрешено использовать внутреннюю константу "xyzabc" в результате выражения конкатенации.

Если в конце я добавлю следующее утверждение:

    System.out.println(x == "xyzabc");

оно всегда будет печатать false ... при условии, что компилятор соответствует спецификации языка Java.

16
ответ дан 3 revs 22 April 2015 в 12:57
поделиться

Посмотрите на декомпилированный класс, и вы увидите все :) Ответ должен быть следующим:

  • две строки ("xyz" и "abc") являются только ссылками на позиции в постоянном пуле поэтому они не создаются вашим кодом
  • одна строка создается напрямую (new String("xyz"))
  • конкатенация строк оптимизируется компилятором и изменяется на StringBuilder, поэтому создается последняя строка косвенно

    public java.lang.String method();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=1
     0: new           #2                  // class java/lang/String
     3: dup
     4: ldc           #3                  // String xyz
     6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
     9: astore_1
    10: ldc           #5                  // String abc
    12: astore_2
    13: new           #6                  // class java/lang/StringBuilder
    16: dup
    17: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
    20: aload_1
    21: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    24: aload_2
    25: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    28: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    31: astore_1
    32: aload_1
    33: areturn
    
12
ответ дан Łukasz Dembiński 22 April 2015 в 12:57
поделиться

Ответ: 4 .

Поскольку вы использовали ключевое слово new, Java создаст новый объект String в обычной (не пуловой) памяти, и x будет ссылаться на него. В дополнение к этому, литерал «xyz» будет помещен в пул строк, который снова является другим строковым объектом.

Итак, 4 строковых объекта:

  1. «xyz» (в памяти без пула)
  2. «xyz» (в память пула)
  3. «abc» (в памяти пула)
  4. «xyzabc» (в памяти без пула)

Если бы ваш код был таким:

String x = "xyz";
String y = "abc";
x = x + y;

, то ответ был бы 3 .

Примечание: строка № 4 находится в памяти без пула, поскольку строковые литералы и строки, полученные путем вычисления константных выражений (см. JLS §15.28), являются единственными строками, которые неявно интернированы.

Источник: SCJP Sun Certified Programmer для Java 6 (Страница: 434, Глава 6)

8
ответ дан Ram Patra 22 April 2015 в 12:57
поделиться

Если вы хотите проверить экземпляры, запустите этот фрагмент кода и посмотрите на вывод:

import static java.lang.System.identityHashCode;

public class Program {
    public static void main(String... args) {
        String x = new String("xyz");
        String y = "abc";
        String z = x + y;

        System.out.printf("x: %d | %d\n", identityHashCode(x), identityHashCode(x.intern()));
        System.out.printf("y: %d | %d\n", identityHashCode(y), identityHashCode(y.intern()));
        System.out.printf("z: %d | %d\n", identityHashCode(z), identityHashCode(z.intern()));
    }
}

У меня есть следующий вывод, используя jdk1.7.0_67 :

x: 414853995 | 1719175803
y: 1405489012 | 1405489012
z: 1881191331 | 1881191331

Это всего 4 String экземпляров ...

7
ответ дан Binkan Salaryman 22 April 2015 в 12:57
поделиться

new String(”xyz“) наверняка создаст новый экземпляр. "abc" и "xyz" хранятся в пуле констант класса, x = x + y создает StringBuilder под капотом и, следовательно, создает new String, поэтому количество строк здесь равно 4.


Однако компилятор может заменить x + y константой ("xyzabc").

3
ответ дан Binkan Salaryman 22 April 2015 в 12:57
поделиться

Причина, по которой вы видите разные ответы на вопрос, заключается (частично) в том, что он неоднозначен.

«Сколько объектов String создано с помощью следующего кода?»

Неоднозначность заключается во фразе «создан с помощью следующего кода»:

  • Это спрашивает о количестве объектов String, которые создаются (просто) выполнением кода?

  • Или ... это спрашивая о количестве объектов String, которые должны существовать во время выполнения кода?

Можно утверждать, что код неявно создает объекты String, которые соответствуют литералам, а не когда запускается, но когда он загружен. Однако эти объекты могут использоваться совместно с другим кодом, использующим те же литералы. (И если вы посмотрите достаточно внимательно, возможно, что другие строковые объекты, содержащие те же строки символов, будут созданы в процессе загрузки класса.)


Другая причина, по которой вы видите разные ответы, заключается в том, что это не совсем ясно, сколько строк создано. В различных спецификациях утверждается, что новые объекты String будут создаваться в определенных точках, но существует «пространство для маневра» в отношении того, могут ли промежуточные объекты String создаваться .

Например, JLS утверждает, что new всегда создает новый объект, и что оператор конкатенации строк создает новый объект, за исключением определенных четко определенных случаев (см. Мой другой ответ). Тем не менее, спецификации не запрещают создание других строк за кулисами.


Но в этом случае, если мы предположим, что мы используем современную JVM Hotspot, то:

  • существует 2 строковых объекта (для строковых литералов), прежде чем код начнет выполняться, и
  • 2 новых строковых объекта создаются (оператором new и +) при выполнении кода.

Наличие / создание этих 4 строк гарантируется JLS.

3
ответ дан Stephen C 22 April 2015 в 12:57
поделиться

Я сказал бы , скажем, 4 , потому что:

Вот как:

String x = new String("xyz"); // 2 objects created: the variable and the constant
String y = "abc"; // 1 object created: the variable
x = x + y; // 1 object created: the one by the StringBuilder class
3
ответ дан Community 22 April 2015 в 12:57
поделиться

1.объекты, созданные в области кучи «xyz» // созданные с помощью «String x» и xyzabc // созданные с помощью «x + y» (конкатенация)

2.объекты, созданные в scp (строковая константа) pool) "xyz" // создан для будущих целей, которые недоступны для сборки мусора, а "abc" // создан с помощью литерала 'String y'

, поэтому общее количество созданных объектов в этом случае равно 4

-1
ответ дан krishna kumar mishra 22 April 2015 в 12:57
поделиться

Ответ 4

String x = new String("xyz");//First Object

String y = "abc";//Second Object

x = x + y;//Third, fourth Object
1
ответ дан tobiinformatik 22 April 2015 в 12:57
поделиться

Ответ 5

  1. xyz в памяти без пула
  2. xyz в памяти пула без ссылки
  3. abc в памяти пула со ссылкой
  4. xyz все еще находится в памяти без пула, ссылка изменена на xyzabc в памяти без пула
  5. xyzabc в памяти пула без ссылки
-1
ответ дан keno 22 April 2015 в 12:57
поделиться
Line 1:String x = new String("xyz");
Line 2:String y = "abc";
Line 3:x = x + y;

Строки являются неизменяемыми, поэтому, если необходимо изменить существующую строковую переменную, для назначения будет создан новый объект. Строка 1, строка 2 являются строковыми объектами, где строка 3 является модификацией существующей строковой переменной, поэтому необходимо добавить новое распределение для добавления x + y. Таким образом, он должен создать создает 3 объекта.

1
ответ дан Mohan Raj 22 April 2015 в 12:57
поделиться

Иногда лучше позволить байт-коду говорить. Изучение кода с использованием JAVAP

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #16                 // class java/lang/String
         3: dup
         4: ldc           #18                 // String xyz
         6: invokespecial #20                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
         9: astore_1
        10: ldc           #23                 // String abc
        12: astore_2
        13: new           #25                 // class java/lang/StringBuilder
        16: dup
        17: aload_1
        18: invokestatic  #27                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        21: invokespecial #31                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        24: aload_2
        25: invokevirtual #32                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St
ringBuilder;
        28: invokevirtual #36                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        31: astore_1
        32: return
      LineNumberTable:
        line 6: 0
        line 7: 10
        line 8: 13
        line 9: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      33     0  args   [Ljava/lang/String;
              10      23     1     x   Ljava/lang/String;
              13      20     2     y   Ljava/lang/String;
}

Теперь, как видно из кода

At `0: new` Creates a new String Object 
At `3:dup` ; make an extra reference to the new instance

    At `4:ldc #18` as seen literal "xyz" has been placed in the pool (one string Object) 
At `6: invokespecial;` ; now call an instance initialization method with parameter and creates a object in nonpool memory.
At `9: astore_1` Stores the above reference in local variable 1(i.e x)

Итак, к этому времени у нас есть два объекта String

At `10:ldc #23` as seen literal "abc" has been placed in the pool (third string ) 

    At `12: astore_2` Stores the above reference in local variable (i.e y)

, так что к этому времени у нас есть три объекта String

    28: invokevirtual #36 // Method java/lang/StringBuilder.toString:
()Ljava/lang/String;;(fourth String Object is Created)

Таким образом, у нас есть четыре объекта String в этом коде.

Поскольку я новичок в программировании и начал изучать его всего несколько месяцев назад, укажите мне, если я где-то ошибся, и какая верная версия этого. Спасибо:)

1
ответ дан Ankur Anand 22 April 2015 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: