Day17-Java
文章目錄
- Day17-Java
- 1、類集
- 1.1 認識類集
- 1.2 Collection集合介面
- 1.3 List介面簡介
- 1.3.1 ArrayList子類
- 1.3.2 Vector子類
- 面試題:請解釋ArrayList與Vector區別?
- 1.3.3LinkedList子類
- 面試題:請解釋ArrayList與LinkedList區別?
- 1.4 Set介面簡介
- 1.4.1 散列存放的子類:HashSet
- 1.4.2 排序存放的子類:TreeSet
- 1.4.3 關于TreeSet排序的說明
- 1.4.4 關于重復元素的說明
- 面試題:如果兩個hashCode()相同、equals()不同結果是什么?不能消除
- 面試題:如果兩個hashCode()不相同、equals()相同結果是什么?不能消除
- 1.5 集合的輸出操作
- 1.5.1 迭代輸出:Iterator
- 1.5.2 雙向迭代輸出:ListIterator
- 1.5.3 廢棄的介面:Enumeration
- 1.5.4 JDK1.5的支持foreach
1、類集
1.1 認識類集
如果現在要想保存多個物件,肯定使用物件陣列完成,但是物件陣列本身有一個最大問題在于確定了資料的長度,所以后來使用了鏈表完成了動態物件陣列的開發,可是鏈表的開發難度實在是很大,而且如果一個鏈表要想真正的去使用,只依靠之前多撰寫的還不夠,還需要進行一些代碼的調優,
而在JDK1.2之后正式引入了類集的概念,類集是一種動態的物件陣列,屬于各個資料結構的實作類,在整個類集之中主要的組成是一些核心的操作介面:Collection,List,Set,Map,Iterator,Enumeration,
1.2 Collection集合介面
Collection是單個集合保存最大的父介面,而在Collection介面的定義如下:
public interface Collection<E> extends Iterable<E>
從JDK1.5之后Collection介面上追加有泛型應用,這樣的直接好處就是避免了ClassCastException例外,里面的所有的資料的保存型別應該是相同的,對于此類的常用方法有如下幾個:
| 方法名稱 | 型別 | 描述 |
|---|---|---|
| public boolean add(E e) | 普通 | 向集合中添加資料 |
| boolean addAll(Collection<? extends E> c) | 普通 | 向集合添加一組資料 |
| public void clear() | 普通 | 清空集合資料 |
| public boolean contains(Object o) | 普通 | 查詢資料是否存在 |
| public Boolean isEmpty() | 普通 | 判斷集合是否有元素 |
| public Iterator iterator() | 普通 | 取得Iterator介面物件,用于輸出 |
| public boolean remove(Object o) | 普通 | 洗掉資料,需要equals()方法 |
| public int size() | 普通 | 取得集合的長度 |
| public Object[] toArray() | 普通 | 將集合資料回傳 |
在開發之中,add()和iterator()方法使用率極高,其他的方法幾乎使用不到,介面只是一個存盤資料的標準,而并不能區分存盤型別,例如:如果要存放資料可能需要區分重復與不重復,所以在實際的開發之中,往往會去考慮使用Collection介面的子介面:List(允許重復)、Set(不允許重復),

1.3 List介面簡介
List是Collection的一個最常用的子介面,并且允許重復的子介面,
| 方法名稱 | 型別 | 描述 |
|---|---|---|
| public E get(int index) | 普通 | 取得指定索引位置上的資料 |
| public E set(int index,E element) | 普通 | 修改指定索引上的資料 |
| public ListIterator listIterator() | 普通 | 為ListIterator介面實體化 |
List子介面與Collection介面相比最大的特點在于其有一個get()方法,可以根據索引取得內容,但是List本身還屬于我們的一個介面而如果取得介面的實體化物件就必須有子類,在List介面下有三個常用子類:ArrayList、Vector、LinkedList,

最終的操作應該還是以介面為主,那么既然要以介面為主,所以所有的方法只參考介面的定義即可,
1.3.1 ArrayList子類
ArrayList是一個針對于List介面的陣列操作實作,
List基本操作
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new ArrayList<>();//此時集合里面只適合保存String型別資料
System.out.println(all.size() + " " + all.isEmpty());
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
System.out.println(all.contains("zsr~"));
System.out.println(all.contains("zsr"));
System.out.println(all);
}
}
通過我們的代碼我們可以證實List允許保存重復資料,
List中存在get()方法,可以利用get()方法結合索引取得資料,
List的get()方法
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new ArrayList<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
for (int i = 0; i < all.size(); i++) {
System.out.println(all.get(i));
}
}
}
但是千萬記住,get()方法是List子介面的,如果現在使用不是List而是Collection,對于此時的資料取出,只能夠將集合變為物件陣列的操作了,
(開發一般不使用)Collection進行輸出處理并取出資料
package com.day17.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
Collection<String> all = new ArrayList<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
//操作以Object形式回傳,那么就有可能需要向下轉型,有可能造成ClassCastException的安全隱患
Object result [] = all.toArray();//變為Object物件陣列
System.out.println(Arrays.toString(result));
}
}
集合與簡單Java類
在實際的開發之中,集合里面保存最多的資料型別,就是簡答java類,
向集合保存簡單java類
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
class Person{
private String name;
private Integer age;
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this == obj){
return true;
}
if (obj == null){
return false;
}
if(!(obj instanceof Person)){
return false;
}
Person per = (Person) obj;//這個物件自己操作可以向下轉型
return this.name.equals(per.name) && this.age.equals(per.age);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class ListDemo {
public static void main(String[] args) {
List<Person> all = new ArrayList<>();
all.add(new Person("張三",10));
all.add(new Person("李四",21));
all.add(new Person("王五",19));
//對于remove()、contains()方法必須類中有equals()的支持
all.remove(new Person("李四",21));
System.out.println(all.contains(new Person("李四",21)));
for (int i = 0; i < all.size(); i++) {
System.out.println(all.get(i));
}
}
}
該List集合如果使用remove()、contains()方法必須有equals()方法的支持,簡單的java類里面的使用是很少使用,
1.3.2 Vector子類
Vector是舊的子類,這個類是從JDK1.0退出,ArrayList實在JDK1.2推出,
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new Vector<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
for (int i = 0; i < all.size(); i++) {
System.out.println(all.get(i));
}
}
}
面試題:請解釋ArrayList與Vector區別?
| 區別 | ArrayList | Vector |
|---|---|---|
| 歷史時間 | JDK1.2 | JDK1.0 |
| 處理形式 | 異步處理,形式更高 | 同步處理,性能降低 |
| 資料安全 | 非執行緒安全 | 執行緒安全 |
| 輸出形式 | Iterator、ListIterator、foreach | Iterator、ListIterator、foreach、Enumeration |
1.3.3LinkedList子類
在List介面里面還有一個LinkedList子類,如果向我們的父介面轉型的話,使用的形式和之前沒有任何的區別,
package com.day17.demo;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new LinkedList<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
for (int i = 0; i < all.size(); i++) {
System.out.println(all.get(i));
}
}
}
面試題:請解釋ArrayList與LinkedList區別?
| 區別 | ArrayList | LinkedList |
|---|---|---|
| 構造方法 | public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } | public LinkedList() { } |
| 開辟長度 | 開辟定長的大小 | 動態開辟 |
| 時間復雜度 | 時間復雜度為1 | 時間復雜度為n |
1.4 Set介面簡介
Set介面與List介面最大的區別就是內容是不允許重復的,通知Set和List最大的區別還有一個就是
set介面沒有對Collection介面進行擴充,而List對Collection介面進行了擴充,由于jdk1.8的原因,所以在collection介面也提供有一些default方法,而這寫方法并沒有在Set介面里面出現,也就是說set介面里面不可能使用get()方法進行處理,而在Set子介面里面有我們常用的子類HashSet、TreeSet,

1.4.1 散列存放的子類:HashSet
Hash(哈希)屬于一種演算法,這種演算法的核心意義指的是找空保存演算法,所以只要一看見Hash就是說沒有順序的保存,
觀察Set介面的使用
package com.day17.demo;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> all = new HashSet<>();
all.add("Hello");
all.add("zsr");
all.add("zsr");
all.add("Abc");
System.out.println(all);
}
}
保存資料在輸出之后發現,重復的資料沒有了,并且其本身的保存也是沒有任何順序的,
1.4.2 排序存放的子類:TreeSet
如果現在希望Set集合之中保存的資料有順序,那么就通過TreeSet進行Set介面的實體化,
使用TreeSet實體化介面
package com.day17.demo;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> all = new TreeSet<>();
all.add("C");
all.add("C");
all.add("A");
all.add("B");
all.add("D");
System.out.println(all);
}
}
現在發現所有的保存的資料沒有重復且有順序,TreeSet使用的是一個升序排列的模式完成的,
1.4.3 關于TreeSet排序的說明
通過之前的程式可以發現,使用TreeSet實體化Set介面之中,所有保存的資料都是有序的,那么在這種情況下,那么如果說使用一個自定義的類呢?
那么這個時候如果這個類的物件要進行排序的話,則這個類必須實作Comparable介面,設定比較規則,但是在這種情況下有一點必須注意:一旦使用了Comparable的話,類之中所有的屬性都必須寫進排序規則,
自定義排序
package com.day17.demo;
import java.util.Set;
import java.util.TreeSet;
class Personn implements Comparable<Personn>{
private String name;
private Integer age;
public Personn(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "person [name=" + this.name + ", age=" + this.age + "]\n";
}
@Override
public int compareTo(Personn o) {
// TODO Auto-generated method stub
if(this.age > o.age){
return 1;
}else if (this.age < o.age){
return 0;
}else{
return this.name.compareTo(o.name);
}
}
}
public class TreeSetDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Set<Personn> all=new TreeSet<Personn>();
all.add(new Personn("張三",20));
all.add(new Personn("張三",20));
all.add(new Personn("李四",20));
all.add(new Personn("王五",30));
all.add(new Personn("趙六",40));
System.out.println(all);
}
}
因為在實際開發之中TreeSet的使用實在是過于麻煩了,在專案開發的簡單java類是根據資料庫表的設計而來的,如果一張資料表的欄位過多,你這個類得寫死,

TreeSet子類依靠Compara()方法的回傳值是否為0來判斷是否為重復元素.
1.4.4 關于重復元素的說明
在使用TreeSet子類進行資料保存的時候,重復元素的判斷依靠的是Comparable介面完成的,這并不是全部Set介面判斷重復元素的方式,因為如果使用的是HashSet子類,由于其Comparable沒有任何關系,所以他判斷重復重復元素的主要依靠的是兩個方法:
- hash碼:public int hashCode();
- 物件比較:public Boolean equals(Object obj)
在進行物件比較的程序之中,首先會使用hashCode()與保存在集合之中的物件的hashCode()進行比較,如果代碼相同,則再使用equals()方法進行內容的比較,如果全部相同,則為相同元素,
package com.day17.demo;
import java.util.Set;
import java.util.TreeSet;
class Personn implements Comparable<Personn>{
private String name;
private Integer age;
public Personn(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Personn other = (Personn) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "person [name=" + this.name + ", age=" + this.age + "]\n";
}
@Override
public int compareTo(Personn o) {
// TODO Auto-generated method stub
if(this.age > o.age){
return 1;
}else if (this.age < o.age){
return 0;
}else{
return this.name.compareTo(o.name);
}
}
}
public class TreeSetDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Set<Personn> all=new TreeSet<Personn>();
all.add(new Personn("張三",20));
all.add(new Personn("張三",20));
all.add(new Personn("李四",20));
all.add(new Personn("王五",30));
all.add(new Personn("趙六",40));
System.out.println(all);
}
}
? 如果要想標識出物件的唯一性,一定需要hashCode()、equals()共同作用,
面試題:如果兩個hashCode()相同、equals()不同結果是什么?不能消除
面試題:如果兩個hashCode()不相同、equals()相同結果是什么?不能消除
? 物件判斷必須兩個都要實作,

1.5 集合的輸出操作
在之前所介紹的都屬于單值集合的基本操作,可是對于集合有一個最重要的問題就是如何進行集合內容的輸出操作,而這個問題在Java的類集框架之中給出了四種輸出方式:Iterator,ListIterator,Enumeration,foreach,
1.5.1 迭代輸出:Iterator

| public boolean hasNext() | 判斷是否有下一個元素 |
|---|---|
| public E next() | 取得當前元素 |
| public default void remove() | 洗掉元素 |
標準Iterator
package com.day17.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new ArrayList<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("world~!");
all.add("zsr~");
Iterator<String> iter = all.iterator();//實體化Iterator
while(iter.hasNext()){
String str = iter.next();
System.out.println(str);
}
}
}
對于Iterator介面中提供的remove()方法主要解決的就是集合內元素洗掉的問題
remove操作
package com.day17.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> all = new ArrayList<>();//此時集合里面只適合保存String型別資料
all.add("Hello");
all.add("Hello"); //重復資料
all.add("a");
all.add("world~!");
Iterator<String> iter = all.iterator();//實體化Iterator
while(iter.hasNext()){
String str = iter.next();
if("a".equals(str)){
all.remove("a");//如果使用此操作后面的中斷執行了
//iter.remove();//如果不中斷后續輸出,則執行
continue ;
}
System.out.println(str);
}
}
}
以后只要是見到了集合的輸出操作,永遠都是用Iterator介面完成,
1.5.2 雙向迭代輸出:ListIterator
Iterator可以完成的是由前向后的單項輸出操作,如果現在希望可以完成由前向后,由后向前的輸出的話,那么就可以利用ListIterator介面完成,此介面是Iterator的子介面,在ListIterator介面主要使用一下兩個擴充方法:
判斷是否有前一個元素:public Boolean hasPrevious();
取出前一個元素:public E previous(),
但是如果要想取得ListIterator介面的實體化物件,Collection沒有這樣的方法支持,這個方法在List介面之中存在:
Public ListIterator listIterator()
執行雙向迭代
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
List<String> all=new ArrayList<String>();
all.add("hello");
all.add("hello");
all.add("world");
ListIterator<String> ite=all.listIterator();
System.out.println("由前向后");
while(ite.hasNext()){
String str=ite.next();
System.out.print(str + "、");
}
System.out.println();
System.out.println("由后向前");
while(ite.hasPrevious()){
String str=ite.previous();
System.out.print(str + "、");
}
}
}
但是對于由后向前的操作,在進行之前一定發生由前向后的輸出,由于此輸出介面只有List可以使用,所以在開發之中幾乎不會出現,
1.5.3 廢棄的介面:Enumeration
Enumeration是一個最早的輸出介面,最早成為列舉輸出,在JDK1.0的時候就已經推出了,并且在JDK1.5的時候將其功能進行擴充,主要就是增加了泛型,在Enumeration介面里只定義了兩個方法:
判斷是否有下一個元素:public Boolean hasMoreElements()
取得當前元素:public E nextElement()
不過要想取得Enumeration的實體化物件,不能依靠Collection介面了,之能夠依靠Vector類完成,在Vector子類之中定義了一個方法:public Enumeration elements(),
使用Enumertaion進行輸出
package com.day17.demo;
import java.util.Enumeration;
import java.util.Vector;
public class IteratorTest {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Vector<String> all=new Vector<String>();
all.add("hello");
all.add("hello");
all.add("world");
Enumeration<String> ite=all.elements();
while(ite.hasMoreElements()){
String str=ite.nextElement();
System.out.println(str);
}
}
}
從開發而言,首先考慮的絕對不是Enumeration,考慮的肯定是Iterator,只有在必須使用的時候才用它,
1.5.4 JDK1.5的支持foreach
對于foreach輸出除了可以進行陣列的輸出以外,還可以進行集合的輸出,
使用foreach
package com.day17.demo;
import java.util.ArrayList;
import java.util.List;
public class IteratorTest {
public static void main(String[] args) {
// TODO 自動生成的方法存根
List<String> all=new ArrayList<String>();
all.add("hello");
all.add("hello");
all.add("world");
for(String x : all){
System.out.println(x);
}
}
}
使用foreach并不是一個被廣泛認可的操作代碼形式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296584.html
標籤:其他
上一篇:鏈表常見面試題( 建議收藏!!)
下一篇:python每日演算法 | 圖文挑戰十大排序演算法DAY1,再也不用擔心面試官問冒泡、選擇、插入排序!持續更新,收藏起來?
