中 程 복습 과정에서 이전 학습이 체계적이지 않고 백 테스트 문제가 더 이상 졸업할 수 없다는 것을 느꼈습니다. 예를 들어 문자열은 고정 길이이고 StringBuffer 및 StringBuilder의 길이는 변경될 수 있습니다. . 조금 더 깊이 물어보고 왜 이렇게 차이가 나느냐고 물어보면 어이가 없어 면접관을 귀여운 표정으로 바라볼 수밖에 없습니다.
따라서 언제 어떤 클래스를 사용해야 하는지 이해할 수 있도록 컬렉션 아키텍처는 어떤지, 관련 상속 및 인터페이스 구현은 무엇인지 등 학습 내용을 기사 작성 형식으로 체계적으로 요약하고 싶습니다. , 그리고 수업 간의 차이점은 함께 협력해야만 문제 해결 방법을 알 수 있습니다.
이 기사 시리즈는 Java 기술 취업 지원자, 대학의 컴퓨터 전공 학생, 교육 기관에서 Java를 배우는 초보자에게 적합합니다.
1.1 컬렉션 아키텍처 이해
우리는 모두 ArrayList 클래스를 사용하여 객체를 추가하고 add() 메소드를 사용하여 객체를 제거했습니다. 모두 우리에게 친숙합니다. 그런데 이러한 방법은 어디서 왔는가? 다음 그림은 이 클래스의 상속 아키텍처 다이어그램입니다.
ArrayList는 클래스만큼 복잡합니다. 전체 Collection 아키텍처를 한 그림에 표시하려면, 아마도 거미줄처럼 얽혀있을 것입니다. 이를 단순화하고 덜 중요한 인터페이스와 구현 클래스를 무시하면 다음 아키텍처 다이어그램을 얻을 수 있습니다.
그림에서 볼 수 있듯이 Collection은 Iterable이라는 또 다른 인터페이스를 구현한 인터페이스입니다. Collection에는 이를 직접 구현하는 세 가지 인터페이스, 즉 List, Set 및 Queue가 있습니다. List 아래에는 ArrayList와 LinkedList라는 두 가지 구현 클래스가 있습니다. 일반적으로 사용되는 Set의 구현 클래스는 TreeSet과 HashSet입니다. Queue 아래에는 Deque 인터페이스 구현이 있고 그 아래에는 ArrayDeque 구현 클래스가 있습니다.
이 그림은 이 일련의 기사의 핵심이 될 것이며 나중에 반복적으로 언급될 것입니다. 컬렉션 아키텍처 다이어그램이라고 할 수 있으며 각 기사에서는 그 일부를 소개합니다. 이 그림을 익히는 것은 이해와 학습에 도움이 될 뿐만 아니라 기억에도 도움이 됩니다. 어떤 클래스가 어떤 인터페이스를 구현하고 어떤 클래스를 상속하는지에 대한 상세하고 포괄적인 상속 관계 및 구현 아키텍처에 대해서는 API 문서에서 쿼리할 수 있습니다.
1.2 List with index
List는 Collection 인터페이스를 구현하므로 List는 컬렉션이고 기능은 객체를 수집하는 것이며 특징은 수집된 데이터를 기록하는 것이라고 할 수 있습니다. 인덱스 개체 순서의 형태입니다. List의 일반적인 구현 클래스는 방금 언급한 아키텍처 다이어그램의 ArrayList입니다. 이를 잊어버린 독자는 앞으로 돌아가서 살펴보세요.
1 /** 2 * ArrayList的实验用例 3 */ 4 5 import java.util.*; 6 7 public class Student { 8 public static void main(String[] args) { 9 List list = new ArrayList(); //使用JavaSE的List和ArrayList10 Scanner scanner = new Scanner(System.in);11 String name;12 while(true) {13 System.out.print("学生签到:");14 name = scanner.nextLine();15 if(name.equals("quit")) {16 break;17 }18 list.add(name); //实用Add()方法收集对象19 }20 System.out.println("今天上来上课的学生名单:");21 foreach(list);22 }23 24 private static void foreach(List list) {25 for(int i = 0; i < list.size(); i++) {26 String student = (String) list.get(i); //使用get()方法依据索引取得收集的对象27 System.out.println(student);28 }29 }30 }
以上是ArrayList类的一个简单使用例子,模拟的是学生上课签到的情景。强烈建议读者跟我一样自己试着写一个简单用例,尤其是之前很少使用ArrayList的初学者,单纯的看和读跟实际敲代码产生的效果完全不一样。也可以照着我给出的例子敲,偷懒一点的话可以直接复制在机器上跑一遍。
从Collection架构图中可知,LinkedList同样也实现了List接口。就算只是把上面那个实验中的ArrayList全部改为LinkedList,程序照样可以运作,而且效果看起来完全相同。那么问题来了,我们什么时候应该使用ArrayList,什么时候又应该使用LinkedList呢?
1.2.1 ArrayList的特性
卡车和轮船都可以运送货物,我们可以根据不同的情况选择不同的运输方式。如果时间紧、运输量小,而且两个地点都在陆地上(例如北京到南京),那么我们可以使用汽车;如果时间多、运输量大,出发地和目的之间隔着海洋(例如大连到纽约),那么用船运是更好的选择。
刚毕业那会要找工作,为了面试背过“ArrayList像数组,读取速度快,但是需要调整索引的话表现很差;LinkedList像链表,调整索引的表现非常好,但是随机读取的速度比较慢”。那么我们可以问深一句,为什么会这样呢?不妨从源代码中找寻答案。
1 public boolean add(E e) {2 ensureCapacityInternal(size + 1); // Increments modCount!!3 elementData[size++] = e;4 return true;5 }
上面这一段是JavaSE的源代码,我们可以看到ArrayList中的add()方法非常简单,跟我们平时使用数组一样。查看源代码中更多内容你会发现,ArrayList内部就是使用Object数组来保存所收集的对象,这就是为什么说“ArrayList就像数组”的原因。在考虑是否使用ArrayList的时候,我们可以相当于考虑是否要使用数组的特性。
1.2.2 LinkedList的特性
在学习Collection架构的时候,我们不妨可以多看源代码,看的时候优先比较几个基本方法的实现,例如add()、remove()等。从这些方法的实现,我们就可以看到不同实现类的特性。
public boolean add(E e) { linkLast(e);return true; }/** * Links e as last element. */void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null); last = newNode;if (l == null) first = newNode;elsel.next = newNode; size++; modCount++; }
看到LinkdedList.add()的源代码,我们会发现其实现方式跟链表的实现如出一辙。如果last结点为null,那么说明链表为空,所以新添加的结点为头结点。如果last结点不等于null,那么把新添加的结点设为last的下一个结点,作为新的尾结点。
根据链表的特性,我们可以很快总结两点点特性:1.想要指定索引随机存取时,链接方式都得使用从第一个元素开始查找下一个元素的方式,效率比较糟糕;2.链接的每个元素都会参考下一个元素,这有利于调整索引顺序。
1.2.3 List总结
作为Collection三大阵营之一的List,最大的特点就是索引,我们可以通过索引做到随机存取。
List中常用的实现有ArrayList和LinkedList,各自的特性可以分别参考数组和链表。在比较它们之间区别的过程中,我们看了源代码,提倡在比较同一接口不同实现类时重点查看它们共同需要实现的方法,例如Collection中规定的add(),remove()等。
面试中常见的List实现类其实还有Vector,其特性与ArrayList相同。不同在于Vector具有线程安全的特性,性能开销比较大,具体的内容会放在以后关于多线程的文章里。
위 내용은 JavaSE의 Collection에 대한 예제 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!