List <Integer>를 List <String>으로 변환


105

정수 목록이 있고 List<Integer>모든 정수 개체를 문자열로 변환하여 새로운 List<String>.

당연히 새를 만들고 각 정수를 List<String>호출하는 목록을 반복 할 수 String.valueOf()있지만 더 나은 (read : more automatic ) 방법 이 있는지 궁금 합니다.

답변:


77

내가 아는 한, 반복하고 인스턴스화하는 것이 이것을 수행하는 유일한 방법입니다. 다음과 같은 것 (다른 사람에게 도움이 될 수있는 방법을 알고 계실 것입니다) :

List<Integer> oldList = ...
/* Specify the size of the list up front to prevent resizing. */
List<String> newList = new ArrayList<>(oldList.size());
for (Integer myInt : oldList) { 
  newList.add(String.valueOf(myInt)); 
}

단순 할 때 이것을 아름다움이라고합니다.
Elbek

1
원래 포스터는 그가 이것을 생각했지만이 솔루션이 너무 복잡하거나 지루하다고 생각했음을 나타내는 것처럼 보였습니다. 그러나 나는 무엇이 더 쉬울 수 있는지 상상하기가 힘듭니다. 예, 때로는 작업을 완료하기 위해 3-4 줄의 코드를 작성해야합니다.
Jay는

그러나 그것은 당신을 ArrayList에 묶습니다. 원래 목록과 동일한 구현을 사용하여 수행 할 수 있습니까?
alianos- 2013

. @Andreas oldList.getClass () newInstance와는 () 할 것입니다
루이스 마르티네스에게

96

사용 구아바 - 프로젝트에서 구글 컬렉션 , 당신은 사용할 수 transform의 방법을 나열 클래스

import com.google.common.collect.Lists;
import com.google.common.base.Functions

List<Integer> integers = Arrays.asList(1, 2, 3, 4);

List<String> strings = Lists.transform(integers, Functions.toStringFunction());

에서 List반환 된 transform것은 백업 목록 의 보기 입니다. 변환은 변환 된 목록에 대한 각 액세스에 적용됩니다.

그주의 Functions.toStringFunction()발생합니다 NullPointerException확실 목록이 null이 포함되지 않습니다 경우 그렇게 밖에 이용, 널 (null)에 적용 할 때.


1
Functions.toStringFunction 옆에 더 준비 기능 ()가있는 경우 그것은 좋은 일 것이다
ThiamTeck

1
깨끗하지만 빠르지 않을 수도 있습니다. 값당 1 개의 추가 함수 호출?
h3xStream 2010

3
HotSpot은 함수 호출을 인라인 할 수 있습니다. 따라서 충분히 호출되면 차이가 없어야합니다.
Ben Lings

3
나는 이것이 실제로 해결책이기 때문에 이것을 찬성하지 않습니다. 그러나 사람들이 이러한 간단한 작업을 해결하기 위해 라이브러리 종속성을 추가하도록 장려하는 것은 나에게 있어서는 안됩니다.
estani

1
이미 우리 솔루션에서 Guava를 사용하고 있다면 좋은 솔루션입니다.
dudinha-dedalus 2015

86

Java 8을위한 솔루션입니다. Guava보다 약간 길지만 최소한 라이브러리를 설치할 필요는 없습니다.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

//...

List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = integers.stream().map(Object::toString)
                                        .collect(Collectors.toList());

1
toString예제에서는 조금 더 길지만 Guava의 Functions 라이브러리에서 지원하지 않는 변환의 경우 더 짧아집니다. 사용자 정의 함수는 여전히 쉽지만이 Java 8 스트림보다 훨씬 많은 코드입니다
lightswitch05

40

당신이하고있는 일은 괜찮지 만 'Java-it-up'이 필요하다고 느끼면 TransformerApache Commonscollect 메소드 를 사용할 수 있습니다. 예 :

public class IntegerToStringTransformer implements Transformer<Integer, String> {
   public String transform(final Integer i) {
      return (i == null ? null : i.toString());
   }
}

..그리고..

CollectionUtils.collect(
   collectionOfIntegers, 
   new IntegerToStringTransformer(), 
   newCollectionOfStrings);

1
CollectionUtils.collect (collectionOfIntegers, 새로운 org.apache.commons.collections.functors.StringValueTransformer ()); 하지만 StringValueTransformer는 String.valueOf를 사용합니다.
Kannan Ekanath

5
아파치 컬렉션에 대한 새로운 작업이 수행되지 않는 한 제네릭을 수행하지 않습니다.
KitsuneYMG 2010 년

1
이것은 정말로 Java-ing-it입니다. 이것은 관용적 Java가 아니며 함수형 프로그래밍과 비슷합니다. Java 8에서 클로저가 생기면 관용적 Java라고 부를 수 있습니다.
Christoffer Hammarström

당신은 확실히 제네릭의 지원이에 대한 Collections4 (안 오래된 3.X 컬렉션)를 사용하려면 : commons.apache.org/proper/commons-collections/apidocs/org/...
JRA_TLL

"더 많은 OOP 또는 관용적"이되도록 새 클래스를 정의하는 중 ... 이것이 간단한 for-each 루프보다 얼마나 나은지 모르겠습니다. 더 많은 코드가 필요하고 기능이 이동합니다 (익명 클래스로 완화 될 수 있지만 여전히). 이 기능적 스타일은 기능적 언어가 수십 년 동안 제공 한 것처럼 괜찮은 구문 (예 : Java 8 이후 람다 식)이있을 때만 유용하기 시작합니다.
TheOperator

9

String.valueOf의 소스는 다음을 보여줍니다.

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

그다지 중요하지는 않지만 toString을 사용합니다.


9

String.valueOf를 사용하는 대신 .toString (); @ johnathan.holland가 설명하는 일부 자동 복싱을 피합니다.

javadoc은 valueOf가 Integer.toString ()과 같은 것을 반환한다고 말합니다.

List<Integer> oldList = ...
List<String> newList = new ArrayList<String>(oldList.size());

for (Integer myInt : oldList) { 
  newList.add(myInt.toString()); 
}

Tom Hawtin이 '승리 한'답변에서 지적했듯이 List <String>은 인터페이스 일 뿐이므로 인스턴스화 할 수 없습니다.
Stu Thompson

ㅎ 알았어. 시도하지 않고 코드를 작성했습니다. 내 대답에서 수정하겠습니다.
ScArcher2

9

비 JDK 라이브러리로 속임수없이 한 줄짜리 솔루션이 있습니다.

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));

7

Guava 및 Java 8을 사용하는 또 다른 솔루션

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));

3

핵심 Java가 아니고 일반화되지 않았지만 인기있는 Jakarta commons collections 라이브러리에는 이러한 종류의 작업에 대한 몇 가지 유용한 추상화가 있습니다. 특히, 수집 방법을 살펴보십시오.

CollectionUtils

프로젝트에서 이미 커먼즈 컬렉션을 사용하고 있다면 고려해야 할 사항입니다.


4
Apache 컬렉션을 사용하지 마십시오. 오래되고 구식이며 형식이 안전하지 않으며 잘못 작성되었습니다.
KitsuneYMG 2010 년

3

jsight의 대답에서 "권투"에 대해 우려하는 사람들에게 : 아무것도 없습니다. String.valueOf(Object)여기서 사용되며 unboxing int은 수행 되지 않습니다 .

사용 여부 Integer.toString()또는 String.valueOf(Object)가능한 null을 처리하려는 방법에 따라 다릅니다. 예외 (아마도)를 던지거나 목록에 "null"문자열을 포함 하시겠습니까 (아마도). 전자라면, NullPointerException다른 유형 을 던지고 싶 습니까?

또한 jsight의 응답에서 한 가지 작은 결함 List은 인터페이스입니다. 새 연산자를 사용할 수 없습니다. java.util.ArrayList이 경우에는 아마도 a 를 사용할 것입니다 . 특히 목록이 얼마나 오래 걸릴지 미리 알고 있기 때문입니다.


3
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())

2

@Jonathan : 착각 할 수는 있지만이 경우 String.valueOf ()가 String.valueOf (int)에 boxed되는 대신 String.valueOf (Object) 함수를 호출 할 것이라고 믿습니다. String.valueOf (Object)는 null 인 경우 "null"을 반환하고 null이 아닌 경우 Object.toString ()을 호출합니다. 이는 boxing을 포함하지 않아야합니다 (분명히 새 문자열 개체를 인스턴스화하는 작업이 포함됨).


2

디버깅 이외의 목적으로 Object.toString ()을 사용하는 것은 아마도이 경우 두 가지가 기능적으로 동일하더라도 (목록에 null이 없다고 가정) 정말 나쁜 생각이라고 생각합니다. 개발자는 표준 라이브러리에있는 모든 클래스의 toString () 메서드를 포함하여 경고없이 모든 toString () 메서드의 동작을 자유롭게 변경할 수 있습니다.

boxing / unboxing 프로세스로 인한 성능 문제에 대해 걱정하지 마십시오. 성능이 중요한 경우 어레이를 사용하십시오. 정말 중요하다면 Java를 사용하지 마십시오. JVM을 능가하려는 시도는 고통을 초래할뿐입니다.


2

전문가를위한 답변 :

    List<Integer> ints = ...;
    String all = new ArrayList<Integer>(ints).toString();
    String[] split = all.substring(1, all.length()-1).split(", ");
    List<String> strs = Arrays.asList(split);

이것은 작동하지만 비 효율성을 희생합니다. Java 문자열은 문자 당 2 바이트이므로 ","는 정수 자체를 계산하기 전에 정 수당 4 바이트 고정 비용을 추가합니다.
Robert Christian

정규식이 원시 CPU 사이클 효율성 측면에서 더 문제가 될 수 있다고 생각합니다. 메모리 측면에서 합리적인 구현 (의 "Sun"이 비합리적인 구현이라고 가정 String)은 동일한 백업 배열 (에서 all) 을 공유 하므로 실제로 메모리 효율성이 매우 뛰어나며 장기적인 성능에 중요합니다. 물론 요소 중 하나만 유지하고 싶지 않다면 ...
Tom Hawtin-tackline

2

Lambdaj 는 매우 간단하고 읽기 쉬운 방식으로이를 수행 할 수 있습니다. 예를 들어, Integer 목록이 있고 해당 문자열 표현으로 변환하려는 경우 다음과 같이 작성할 수 있습니다.

List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
    public String convert(Integer i) { return Integer.toString(i); }
}

Lambdaj는 결과를 반복하는 동안에 만 변환 함수를 적용합니다.


1

"박싱 오버 헤드"를 피할 수 없습니다. Java의 가짜 제네릭 컨테이너는 객체 만 저장할 수 있으므로 int는 Integer로 박스해야합니다. 원칙적으로 Object에서 Integer 로의 다운 캐스트를 피할 수 있지만 (Object가 String.valueOf와 Object.toString 모두에 충분하기 때문에 무의미하기 때문에) 컴파일러가 그렇게 할 수있을만큼 똑똑한지는 모르겠습니다. String에서 Object 로의 변환은 다소 무의미해야하므로 걱정할 필요가 없습니다.


컴파일러는 그렇게 할만 큼 똑똑하지 않습니다. javac가 실행되면 실제로 모든 제네릭 유형 정보를 제거합니다. 제네릭 컬렉션의 기본 구현은 항상 Object 참조를 저장합니다. 실제로 <T> 매개 변수화를 생략하고 "원시"유형을 얻을 수 있습니다. "List l = new List ()"대 "List <String> l = new List <String> ()". 물론 이것은 "List <String> l = (List <String>) new List <Integer> ()"가 실제로 컴파일 및 실행되지만 분명히 매우 위험하다는 것을 의미합니다.
Dave Dopson 2011 년

1

나는 공간 복잡성의 원칙을 따르는 해결책을 보지 못했습니다. 정수 목록에 많은 수의 요소가 있으면 큰 문제입니다.

It will be really good to remove the integer from the List<Integer> and free
the space, once it's added to List<String>.

반복자를 사용하여 동일한 결과를 얻을 수 있습니다.

    List<Integer> oldList = new ArrayList<>();
    oldList.add(12);
    oldList.add(14);
    .......
    .......

    List<String> newList = new ArrayList<String>(oldList.size());
    Iterator<Integer> itr = oldList.iterator();
    while(itr.hasNext()){
        newList.add(itr.next().toString());
        itr.remove();
    }

1

Streams 사용 : 결과가 정수 목록 ( List<Integer> result) 이라고 가정하면 다음과 같습니다.

List<String> ids = (List<String>) result.stream().map(intNumber -> Integer.toString(intNumber)).collect(Collectors.toList());

그것을 해결하는 방법 중 하나입니다. 도움이 되었기를 바랍니다.


1

원래 목록에서 forEach 메서드를 사용하는 약간 더 간결한 솔루션 :

    List<Integer> oldList = Arrays.asList(1, 2, 3, 4, 5);
    List<String> newList = new ArrayList<>(oldList.size());
    oldList.forEach(e -> newList.add(String.valueOf(e)));

0

재미를 위해 JDK7에 있어야하는 jsr166y fork-join 프레임 워크를 사용하는 솔루션입니다.

import java.util.concurrent.forkjoin.*;

private final ForkJoinExecutor executor = new ForkJoinPool();
...
List<Integer> ints = ...;
List<String> strs =
    ParallelArray.create(ints.size(), Integer.class, executor)
    .withMapping(new Ops.Op<Integer,String>() { public String op(Integer i) {
        return String.valueOf(i);
    }})
    .all()
    .asList();

(면책 조항 : 컴파일되지 않음. 사양이 확정되지 않았습니다. 등)

JDK7에있을 것 같지 않은 것은 withMapping 호출을 덜 장황하게 만드는 약간의 유형 추론 및 구문 적 설탕입니다.

    .withMapping(#(Integer i) String.valueOf(i))

0

이것은 외부 라이브러리를 사용하지 않는 기본적인 작업입니다 (프로젝트에 필요하지 않은 종속성이 발생합니다).

이러한 종류의 작업을 수행하도록 특별히 제작 된 정적 메서드 클래스가 있습니다. 코드가 너무 간단하기 때문에 Hotspot이 최적화를 수행하도록했습니다. 이것은 최근에 내 코드의 테마 인 것 같습니다. 매우 간단한 (간단한) 코드를 작성하고 Hotspot이 마법을 수행하도록합니다. 이와 같은 코드와 관련하여 성능 문제는 거의 발생하지 않습니다. 새 VM 버전이 출시되면 모든 추가 속도 이점 등을 얻을 수 있습니다.

내가 Jakarta 컬렉션을 좋아하는만큼 Generics를 지원하지 않고 LCD로 1.4를 사용합니다. Google 컬렉션은 알파 지원 수준으로 표시되기 때문에 조심합니다!


-1

나는 문제에 대한 객체 지향 솔루션으로 차임하고 싶었습니다.

도메인 개체를 모델링하는 경우 솔루션은 도메인 개체에 있습니다. 여기서 도메인은 문자열 값을 원하는 정수 목록입니다.

가장 쉬운 방법은 목록을 전혀 변환하지 않는 것입니다.

즉, 변환하지 않고 변환하려면 원래 Integer 목록을 List of Value로 변경하십시오. 여기서 Value는 다음과 같습니다.

class Value {
    Integer value;
    public Integer getInt()
    {
       return value;
    }
    public String getString()
    {
       return String.valueOf(value);
    }
}

이것은 목록을 복사하는 것보다 빠르며 메모리를 덜 차지합니다.

행운을 빕니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.