Java Language
기울기
수색…
소개
목록 은 정렬 된 값 모음입니다. Java에서 목록은 Java Collections Framework의 일부입니다. 목록은 구현 java.util.List
확장 인터페이스, java.util.Collection
.
통사론
- ls.add (E 요소); // 요소를 추가합니다.
- ls.remove (E 요소); // 요소를 제거합니다.
- for (E element : ls) {} // 각 원소를 반복한다.
- ls.toArray (new String [ls.length]); // 문자열 목록을 문자열 배열로 변환합니다.
- ls.get (int index); // 지정된 인덱스에있는 요소를 반환합니다.
- ls.set (int index, E element); // 지정된 위치의 요소를 바꿉니다.
- ls.isEmpty (); // 배열에 요소가 없으면 true를 반환하고 그렇지 않으면 false를 반환합니다.
- ls.indexOf (Object o); // 지정된 요소 o의 첫 번째 위치에 대한 인덱스를 반환하거나, 존재하지 않으면 -1을 반환합니다.
- ls.lastIndexOf (Object o); // 지정된 요소 o의 마지막 위치의 인덱스를 반환하거나, 존재하지 않으면 -1을 반환합니다.
- ls.size (); // List에있는 요소의 수를 반환합니다.
비고
목록 은 값의 정렬 된 컬렉션을 저장하는 객체입니다. "주문 됨"은 값이 특정 순서로 저장됨을 의미합니다. 한 항목이 먼저오고 두 번째는 두 번째 등입니다. 개별 값은 일반적으로 "요소"라고합니다. Java 목록은 일반적으로 다음 기능을 제공합니다.
- 목록에는 0 개 이상의 요소가 포함될 수 있습니다.
- 목록에 중복 값이 포함될 수 있습니다. 즉, 요소를 두 번 이상 목록에 삽입 할 수 있습니다.
- 목록은 요소를 특정 순서로 저장합니다. 즉, 요소 하나가 먼저오고, 다음 요소가 오게됩니다.
- 각 요소에는 목록 내의 위치를 나타내는 인덱스 가 있습니다. 첫 번째 요소에는 인덱스 0이 있고, 다음 요소에는 인덱스 1이 있습니다.
- 목록을 사용하면 목록의 시작, 끝 또는 모든 색인에 요소를 삽입 할 수 있습니다.
- 목록에 특정 값이 들어 있는지 테스트하는 것은 일반적으로 목록의 각 요소를 검사하는 것을 의미합니다. 즉,이 검사를 수행하는 시간은 O (n) 이며 목록의 크기에 비례합니다.
끝 이외의 다른 지점에서 값을 목록에 추가하면 다음 요소를 모두 "아래로"또는 "오른쪽으로"이동합니다. 즉, 인덱스 n은 요소를 추가하는 등의 인덱스, N + 1 및 N에 인덱스로 사용될 수있는 요소를 이동시킨다. 예 :
List<String> list = new ArrayList<>();
list.add("world");
System.out.println(list.indexOf("world")); // Prints "0"
// Inserting a new value at index 0 moves "world" to index 1
list.add(0, "Hello");
System.out.println(list.indexOf("world")); // Prints "1"
System.out.println(list.indexOf("Hello")); // Prints "0"
일반 목록 정렬
Collections
클래스는 목록을 정렬하는 두 가지 표준 정적 메서드를 제공합니다.
-
sort(List<T> list)
T extends Comparable<? super T>
있는 곳의리스트에 적용 가능T extends Comparable<? super T>
, -
sort(List<T> list, Comparator<? super T> c)
모든 유형의 목록에 적용 할 수 있습니다.
전자를 적용하려면 정렬되는 목록 요소의 클래스를 수정해야합니다. 이는 항상 가능하지는 않습니다. 또한 기본 정렬, 다른 상황에서 다른 정렬 순서가 필요할 수도 있고 정렬이 하나의 작업 일 수도 있기 때문에 바람직하지 않을 수도 있습니다.
다음 클래스의 인스턴스 인 객체를 정렬하는 작업이 있다고 가정 해보십시오.
public class User {
public final Long id;
public final String username;
public User(Long id, String username) {
this.id = id;
this.username = username;
}
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
}
Collections.sort(List<User> list)
를 사용하려면 User
클래스를 수정하여 Comparable
인터페이스를 구현해야합니다. 예를 들어
public class User implements Comparable<User> {
public final Long id;
public final String username;
public User(Long id, String username) {
this.id = id;
this.username = username;
}
@Override
public String toString() {
return String.format("%s:%d", username, id);
}
@Override
/** The natural ordering for 'User' objects is by the 'id' field. */
public int compareTo(User o) {
return id.compareTo(o.id);
}
}
String
, Long
, Integer
와 같은 많은 표준 Java 클래스는 Comparable
인터페이스를 구현하므로 기본적으로 해당 요소의 목록을 정렬 할 수 있으며 다른 클래스에서 compare
또는 compareTo
구현을 단순화합니다.
위의 수정을 통해 클래스 자연 순서 에 따라 User
객체 목록을 쉽게 정렬 할 수 있습니다. (이 경우 id
값을 기반으로 정렬되도록 정의했습니다.) 예 :
List<User> users = Lists.newArrayList(
new User(33L, "A"),
new User(25L, "B"),
new User(28L, ""));
Collections.sort(users);
System.out.print(users);
// [B:25, C:28, A:33]
그러나 User
객체를 id
아닌 name
으로 정렬하려고한다고 가정합니다. 또는 클래스를 변경하여 Comparable
을 구현할 수 없었던 것으로 가정합니다.
Comparator
인수를 사용하는 sort
메소드가 유용합니다.
Collections.sort(users, new Comparator<User>() {
@Override
/* Order two 'User' objects based on their names. */
public int compare(User left, User right) {
return left.username.compareTo(right.username);
}
});
System.out.print(users);
// [A:33, B:25, C:28]
Java 8에서는 익명 클래스 대신 람다 를 사용할 수 있습니다. 후자는 one-liner로 감소합니다.
Collections.sort(users, (l, r) -> l.username.compareTo(r.username));
더욱이, Java 8에서는 List
인터페이스에 기본 sort
메소드를 추가하여 정렬을 훨씬 더 단순화합니다.
users.sort((l, r) -> l.username.compareTo(r.username))
목록 만들기
귀하의 목록 유형을주는
목록을 만들려면 유형 (모든 클래스, 예 : String
)이 필요합니다. 이것은 귀하의 List
유형입니다. List
는 지정된 유형의 객체 만 저장합니다. 예 :
List<String> strings;
"string1"
, "hello world!"
저장할 수 "hello world!"
, "goodbye"
등이 있지만 9.2
저장할 수는 없습니다.
List<Double> doubles;
9.2
저장할 수 있지만 "hello world!"
저장할 수 없습니다 "hello world!"
.
목록 초기화하기
위의 목록에 뭔가를 추가하려고하면 strings
과 doubles
모두 null 이기 때문에 NullPointerException이 발생합니다!
목록을 초기화하는 방법에는 두 가지가 있습니다.
옵션 1 : List를 구현하는 클래스 사용
List
는 생성자가 아니라 클래스가 재정의해야하는 메서드를 포함하는 인터페이스입니다. ArrayList
는 가장 일반적으로 사용되는 List
이지만 LinkedList
도 일반적입니다. 그래서 우리는 다음과 같이 목록을 초기화합니다.
List<String> strings = new ArrayList<String>();
또는
List<String> strings = new LinkedList<String>();
Java SE 7부터는 다이아몬드 연산자를 사용할 수 있습니다.
List<String> strings = new ArrayList<>();
또는
List<String> strings = new LinkedList<>();
옵션 2 : Collections 클래스 사용
Collections
클래스는 List
변수없이 List를 만드는 두 가지 유용한 메소드를 제공합니다.
-
emptyList()
: 빈 목록을 반환합니다. -
singletonList(T)
:singletonList(T)
유형의 목록을 만들고 지정된 요소를 추가합니다.
기존 List
을 사용하여 데이터를 채우는 방법
-
addAll(L, T...)
: 지정된 모든 요소를 첫 번째 매개 변수로 전달 된 목록에 추가합니다.
예 :
import java.util.List; import java.util.Collections; List<Integer> l = Collections.emptyList(); List<Integer> l1 = Collections.singletonList(42); Collections.addAll(l1, 1, 2, 3);
위치 액세스 작업
List API에는 위치 액세스 조작을위한 8 가지 메소드가 있습니다.
-
add(T type)
-
add(int index, T type)
-
remove(Object o)
-
remove(int index)
-
get(int index)
-
set(int index, E element)
-
int indexOf(Object o)
-
int lastIndexOf(Object o)
그래서 우리가리스트를 가지고 있다면 :
List<String> strings = new ArrayList<String>();
그리고 우리는 "Hello world!"라는 문자열을 추가하기를 원했습니다. 와 "안녕 세상!" 그것으로, 우리는 그렇게 할 것입니다 :
strings.add("Hello world!");
strings.add("Goodbye world!");
그리고 우리 목록에는 두 가지 요소가 포함됩니다. 이제 "프로그램 시작"을 추가하고 싶다고 말하면됩니다. 목록 앞에 . 우리는 이렇게 할 것입니다 :
strings.add(0, "Program starting!");
참고 : 첫 번째 요소는 0입니다.
자, 만약 우리가 "안녕히 계십시오!" 라인, 우리는 이렇게 할 수 :
strings.remove("Goodbye world!");
그리고 첫 번째 줄을 없애고 싶다면 (이 경우 "프로그램 시작!"이라고 할 수 있습니다. 다음과 같이 할 수 있습니다 :
strings.remove(0);
노트 :
리스트 요소의 추가와 삭제는리스트를 변경해,리스트가 동시에 반복 처리되고있는 경우에
ConcurrentModificationException
가되는 일이 있습니다.목록 클래스, 사용 된 방법 및 목록의 시작, 끝 또는 중간에 요소 추가 / 제거 여부에 따라 요소 추가 및 제거는
O(1)
또는O(N)
일 수 있습니다.
지정된 위치에서 목록의 요소를 검색하려면 E get(int index);
List API의 메소드 예 :
strings.get(0);
목록의 첫 번째 요소를 반환합니다.
set(int index, E element);
를 사용하여 지정된 위치의 모든 요소를 바꿀 수 있습니다 set(int index, E element);
. 예 :
strings.set(0,"This is a replacement");
그러면 목록의 첫 번째 요소로 "This is a replacement"문자열이 설정됩니다.
참고 : set 메서드는 0 위치에 요소를 덮어 씁니다. 새 String을 0 위치에 추가하지 않고 이전 위치를 1 위치로 푸시합니다.
int indexOf(Object o);
인수로 전달 된 객체가 처음 나타나는 위치를 반환합니다. 목록에 오브젝트가 _ 생하지 않으면 -1 값이 리턴됩니다. 앞의 예제를 계속하면 다음을 호출합니다.
strings.indexOf("This is a replacement")
0은 우리 목록의 0 번째 위치에 "This is a replacement"문자열을 설정할 때 반환 될 것으로 예상됩니다. 목록에 하나 이상의 항목이있는 경우 int indexOf(Object o);
언급 된 바와 같이 첫 번째 발생 색인이 반환됩니다. int lastIndexOf(Object o)
를 호출하면 목록에서 마지막으로 발견 된 색인을 검색 할 수 있습니다. 그래서 우리가 다른 "This is a replacement"를 추가하면 :
strings.add("This is a replacement");
strings.lastIndexOf("This is a replacement");
이번에는 1이 반환되고 0은 반환되지 않습니다.
목록의 요소 반복하기
예를 들어, "hello", "how", "are", "you?"네 요소가 포함 된 String 유형의 List가 있다고 가정 해 보겠습니다.
각 요소를 반복하는 가장 좋은 방법은 for-each 루프를 사용하는 것입니다.
public void printEachElement(List<String> list){
for(String s : list){
System.out.println(s);
}
}
어느 것이 인쇄 할 것인가?
hello,
how
are
you?
같은 줄에 모두 인쇄하려면 StringBuilder를 사용할 수 있습니다.
public void printAsLine(List<String> list){
StringBuilder builder = new StringBuilder();
for(String s : list){
builder.append(s);
}
System.out.println(builder.toString());
}
인쇄 할 것입니다 :
hello, how are you?
또는 요소 인덱스 작성 ( ArrayList의 i 번째 인덱스에서 요소 액세스에 설명 된대로)을 사용하여 목록을 반복 할 수 있습니다. 경고 :이 방법은 링크 된 목록에 비효율적입니다.
목록 A에있는 목록 B에서 요소 제거
당신은이 목록의 A와 B가 있고, 당신은 B에서이 경우 방법은 당신이에있는 모든 요소를 제거한다고 가정하자
List.removeAll(Collection c);
#예:
public static void main(String[] args) {
List<Integer> numbersA = new ArrayList<>();
List<Integer> numbersB = new ArrayList<>();
numbersA.addAll(Arrays.asList(new Integer[] { 1, 3, 4, 7, 5, 2 }));
numbersB.addAll(Arrays.asList(new Integer[] { 13, 32, 533, 3, 4, 2 }));
System.out.println("A: " + numbersA);
System.out.println("B: " + numbersB);
numbersB.removeAll(numbersA);
System.out.println("B cleared: " + numbersB);
}
이거 인쇄 할거야.
A : [1, 3, 4, 7, 5, 2]
B : [13, 32, 533, 3, 4, 2]
B 삭제 : [13, 32, 533]
2 개의 목록 사이의 공통 요소 찾기
A와 B의 두 목록이 있고 두 목록에 존재하는 요소를 찾아야한다고 가정합니다.
List.retainAll()
메서드를 호출하면됩니다.
예:
public static void main(String[] args) {
List<Integer> numbersA = new ArrayList<>();
List<Integer> numbersB = new ArrayList<>();
numbersA.addAll(Arrays.asList(new Integer[] { 1, 3, 4, 7, 5, 2 }));
numbersB.addAll(Arrays.asList(new Integer[] { 13, 32, 533, 3, 4, 2 }));
System.out.println("A: " + numbersA);
System.out.println("B: " + numbersB);
List<Integer> numbersC = new ArrayList<>();
numbersC.addAll(numbersA);
numbersC.retainAll(numbersB);
System.out.println("List A : " + numbersA);
System.out.println("List B : " + numbersB);
System.out.println("Common elements between A and B: " + numbersC);
}
정수 목록을 문자열 목록으로 변환
List<Integer> nums = Arrays.asList(1, 2, 3);
List<String> strings = nums.stream()
.map(Object::toString)
.collect(Collectors.toList());
그건:
- 목록에서 스트림 만들기
-
Object::toString
사용해 각 요소를 매핑한다 -
Collectors.toList()
사용하여List
String
값을 수집하십시오.
ArrayList에서 요소 만들기, 추가 및 제거
ArrayList
는 Java의 inbuilt 데이터 구조 중 하나입니다. 요소 (객체)를 저장하기 위해 동적 배열 (데이터 구조의 크기를 먼저 선언 할 필요가없는)입니다.
그것은 AbstractList
클래스를 확장하고 List
인터페이스를 구현합니다. ArrayList
에는 삽입 순서를 유지하는 중복 요소가 포함될 수 있습니다. ArrayList
클래스는 비 동기화되어 있으므로 ArrayList
와의 동시성을 처리 할 때는주의를 기울여야합니다. ArrayList
는 인덱스 단위로 작동하므로 임의 액세스가 허용됩니다. 요소가 배열 목록에서 제거 될 때 자주 발생하는 이동 때문에 ArrayList
에서 조작이 느립니다.
다음과 같이 ArrayList
를 만들 수 있습니다.
List<T> myArrayList = new ArrayList<>();
여기서 T
( Generics )는 ArrayList
내에 저장 될 형식입니다.
ArrayList
의 형태는 임의의 Object가 될 수 있습니다. 형식은 원시 형식이 될 수 없습니다 ( 래퍼 클래스를 대신 사용하십시오).
ArrayList
요소를 추가하려면 add add()
메서드를 사용 add()
.
myArrayList.add(element);
또는 특정 색인에 항목을 추가하려면 :
myArrayList.add(index, element); //index of the element should be an int (starting from 0)
ArrayList
에서 항목을 제거하려면 remove remove()
메서드를 사용합니다.
myArrayList.remove(element);
또는 특정 색인에서 항목을 제거하려면 다음을 수행하십시오.
myArrayList.remove(index); //index of the element should be an int (starting from 0)
List 요소의 적절한 대체
이 예제는 대체 요소가 대체되는 요소와 동일한 위치에 있는지 확인하면서 List
요소를 대체하는 것입니다.
다음 방법을 사용하여이 작업을 수행 할 수 있습니다.
- set (int index, T type)
- int indexOf (T 형)
요소 "Program starting!", "Hello world!"를 포함하는 ArrayList
를 생각해보십시오. 와 "안녕 세상!"
List<String> strings = new ArrayList<String>();
strings.add("Program starting!");
strings.add("Hello world!");
strings.add("Goodbye world!");
바꾸려는 요소의 색인을 알고 있다면 간단히 set
을 다음과 같이 사용할 수 있습니다.
strings.set(1, "Hi world");
색인을 모른다면 먼저 색인을 검색 할 수 있습니다. 예 :
int pos = strings.indexOf("Goodbye world!");
if (pos >= 0) {
strings.set(pos, "Goodbye cruel world!");
}
노트:
-
set
조작으로ConcurrentModificationException
는 발생하지 않습니다. -
set
연산은ArrayList
대해서는 빠르지 만 (O(1)
),LinkedList
대해서는 느립니다 (O(N)
). -
ArrayList
또는LinkedList
에 대한indexOf
검색은 느립니다 (O(N)
).
수정 불가능한 목록 만들기
Collections 클래스는 목록을 수정할 수 없도록 만드는 방법을 제공합니다.
List<String> ls = new ArrayList<String>();
List<String> unmodifiableList = Collections.unmodifiableList(ls);
하나의 항목으로 수정할 수없는 목록을 원하면 다음을 사용할 수 있습니다.
List<String> unmodifiableList = Collections.singletonList("Only string in the list");
목록에서 객체를 움직입니다.
Collections 클래스를 사용하면 다양한 메서드 (목록은 ls)를 사용하여 목록에서 객체를 이동할 수 있습니다.
목록 반전 :
Collections.reverse(ls);
목록에있는 요소의 위치 회전
rotate 메소드에는 정수 인수가 필요합니다. 이것은 라인을 따라 이동하는 지점이 얼마나 많은 지입니다. 예를 들면 다음과 같습니다.
List<String> ls = new ArrayList<String>();
ls.add(" how");
ls.add(" are");
ls.add(" you?");
ls.add("hello,");
Collections.rotate(ls, 1);
for(String line : ls) System.out.print(line);
System.out.println();
그러면 "안녕, 잘 지냈니?"라는 문구가 인쇄됩니다.
목록에서 요소 주위를 섞기
위의 동일한 목록을 사용하여 목록의 요소를 임의로 섞을 수 있습니다.
Collections.shuffle(ls);
우리는 java.util.Random 객체를 제공하여 무작위로 객체를 배치 할 수 있습니다 :
Random random = new Random(12);
Collections.shuffle(ls, random);
List를 구현하는 클래스 - 찬반론
List
인터페이스는 다른 클래스에 의해 구현됩니다. 각각은 서로 다른 전략으로 구현하고 서로 다른 장단점을 제공 할 수있는 자체 방식을 가지고 있습니다.
List를 구현하고있는 클래스
다음은 java.util.List
인터페이스를 구현하는 Java SE 8의 모든 public
클래스입니다.
- 추상 클래스 :
- AbstractList
- AbstractSequentialList
- 구체적인 수업 :
- ArrayList
- AttributeList
- CopyOnWriteArrayList
- LinkedList
- RoleList
- RoleUnresolvedList
- 스택
- 벡터
시간 복잡성의 관점에서 각 구현의 장단점
ArrayList
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
ArrayList 는, List 인터페이스의 사이즈 변경 가능한 배열 구현입니다. 리스트를 배열에 저장하면, ArrayList 는 배열의 크기를 조작하기위한 메소드 ( List 인터페이스를 구현하는 메소드 이외에)를 제공합니다.
Integer의 ArrayList를 크기 100으로 초기화하십시오.
List<Integer> myList = new ArrayList<Integer>(100); // Constructs an empty list with the specified initial capacity.
- PROS :
크기, isEmpty, get , set , iterator 및 listIterator 작업은 일정한 시간 내에 실행됩니다. 따라서 목록의 각 요소를 가져오고 설정하는 데 소요되는 시간 은 동일 합니다 .
int e1 = myList.get(0); // \
int e2 = myList.get(10); // | => All the same constant cost => O(1)
myList.set(2,10); // /
- 단점 :
배열의 크기에 요소를 추가하는 배열 (정적 구조)을 구현하면 모든 배열에 대해 새로운 할당을 수행해야하기 때문에 많은 비용이 듭니다. 그러나 문서에서 :
add 연산은 상각 된 상수 시간에 실행됩니다. 즉, n 요소를 추가하려면 O (n) 시간이 필요합니다.
요소를 제거하려면 O (n) 시간이 필요합니다.
AttributeList
올 때
CopyOnWriteArrayList
올 때
LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
LinkedList 는 노드라고하는 순차적으로 링크 된 레코드로 구성된 링크 된 데이터 구조를 이중 연결 목록 으로 구현합니다.
정수의 LinkedList 초기화
List<Integer> myList = new LinkedList<Integer>(); // Constructs an empty list.
- PROS :
목록 앞 또는 끝에 요소를 추가하거나 제거하면 일정 시간이 있습니다.
myList.add(10); // \
myList.add(0,2); // | => constant time => O(1)
myList.remove(); // /
- 단점 : 문서에서 :
목록에 색인을 생성하는 작업은 시작 또는 끝 중 지정된 색인에 가까운 쪽부터 목록을 탐색합니다.
다음과 같은 작업 :
myList.get(10); // \
myList.add(11,25); // | => worst case done in O(n/2)
myList.set(15,35); // /
RoleList
올 때
RoleUnresolvedList
올 때
스택
올 때
벡터
올 때