首頁技術文章正文

集合的總結與常見問題解析

更新時間:2018-11-26 來源:黑馬程序員 瀏覽量:

  1、如何定義Collection?

  Collection是一個集合體系的頂層接口,此接口中的方法都是:public abstract。

  可以進行增刪改查的操作:

  增加: -->> boolean add(Object o) 一次添加一個元素,元素可以是Object 的子類,返回true

  boolean addAll(Collection c) 一次添加一批元素,參數(shù)是Collection類型的

  刪除: -->> void clear() 清空集合

  boolean remove(Object o) 一次刪除一個元素,成功刪除,返回true

  boolean removeAll(Collection c) 一次刪除一批,成功,返回true

  查找: -->> boolean contains(Obejct o) 判斷集合中是否包含指定元素

  boolean containsAll(Collection c) 是否包含一批

  boolean isEmpty() 判斷集合是否為空

  int size() 獲取集合中的個數(shù)

  修改: -->> clear() 清空集合中的所有元素

  獲取: -->> int size() 返回集合容器的大小

  集合轉換為數(shù)組:

  Object[] toArray(); 該方法將集合轉為數(shù)組,集合中的每一個元素,作為了數(shù)組一個的元素

  【注意:集合中存儲的是對象的引用,而不是對象本身】

  【注意:接口與接口之間屬于:繼承關系】

  2、錄入用戶在控制臺輸入的信息,可以使用Scanner類

  Scanner sc = new Scanner();

  3、List接口: ---->> public interface List extends Collection

  List是一個繼承了Collection接口的接口,具備了比Collection多的功能。

  特點: ---->> 有序、有角標、可重復。

  此接口的用戶可以對List接口中每個元素的插入位置進行精確地控制。(通過角標獲取集合中的元素)

  增:

  void add(int index,Object element) 指定元素添加的角標,增加一個元素

  boolean addAll(int index,Collection c) 指定位置,增加一批

  刪:

  Element remove(int index) 刪除指定位置的元素,并且返回該元素

  改:

  Element set(int index,Object element) 替換指定位置的元素,需要確定該元素的位置和新元素,返回就元素。

  ListsubList(int fromIndex,int toIndex) 截取子結合,返回一個List,包含頭,不包含尾。

  查:

  Object get(int index) 獲取List結合指定位置的元素

  int indexOf(Object o) 返回此列表中第一次出現(xiàn)的指定元素的索引

  int lastIndexOf(Object o) 倒序查找指定元素的位置

  【注意角標越界:IndexOutOfBoundException // 找不到返回:-1】

  【Object set = new list.get(list.size()-1);】

  【List集合特有的增刪改查方法都跟角標有關系!!!!】

  【問:如何取出List集合中的元素?】

  通過for循環(huán),并使用size()和set()方法可取出List集合中的每一個元素。

  4、ArrayList -->> 是一個List接口的實現(xiàn)類

  具備List集合的特點:有序、有角標、可重復。

  該類內部,維護了一個數(shù)組, 數(shù)組的元素是Object 類.

  在ArrayList 類的構造函數(shù)中初始化的該數(shù)組, 如果沒有顯示的指定數(shù)組的長度,【默認長度是10】

  也就是說: 使用無參數(shù)構造,new ArraList(), 自動創(chuàng)建的數(shù)組長度是60%.

  ArrayList 在添加元素時,都會檢測數(shù)組是否已滿,如果滿了,自動擴容(創(chuàng)建一個新數(shù)組),

  【新數(shù)組長度的是老數(shù)組的1.6倍】

  并且將老數(shù)組中的元素拷貝到了新數(shù)組,使用新數(shù)組繼續(xù)增加元素.

  5、ArrayList使用什么實現(xiàn)的?其優(yōu)缺點是什么?

  ArrayList是使用數(shù)組實現(xiàn)的。

  優(yōu)點:內存地址連續(xù),查找快;

  缺點:增加和刪除元素,需要設計數(shù)組的擴容或者拷貝,效率很低。

  ---->> 總結: 數(shù)組實現(xiàn),查找快,增刪慢。

  ArrayList中的方法:

  boolean contains(Object o) 判斷集合是否包含指定的元素,涉及了元素的比較(對象的比較)

  內部使用了元素的equals()方法。

  String類 重寫了equals()方法

  6、LinkedList ---->> List接口的實現(xiàn)類,具備:有序、有角標、元素可重復的特點?!竞虯rrayList類似】

  LinkedList是一個雙向鏈表,該集合提供了方便操作集合頭和集合尾的方法。

  【如果集合中沒有元素可以獲取或者刪除,則拋:NoSuchElementException】

  LinkedList特有的方法:

  增加:

  void addFirst(Element e)

  void addLast(Element e)

  刪除:

  Object getFirst()

  Object getLast()

  查找:

  Object removeFirst() 移除并返回此列表的第一個元素

  Object removeLast() 移除并返回此列表的最后一個元素

  數(shù)據(jù)結構:

  堆棧:

  void push(Element e) 將元素推入此列表所表示的堆棧

  Element pop() 從此列表所表示的堆棧處彈出一個元素

  【壓棧和彈棧:先進后出,后進先出】

  隊列:

  boolean offer(Element e) 將指定元素添加到此列表的末尾(最后一個元素)

  Element poll() 獲取并移除此列表的頭(第一個元素)

  Element peek() 獲取但不移除列表的頭(第一個元素)

  【隊列的數(shù)據(jù)結構:先進先出】

  返回逆序的迭代器對象:

  descendingIterator() 返回逆序的迭代器對象

  7、LinkedList的實現(xiàn)原理是什么?其優(yōu)缺點?

  LinkedList的實現(xiàn)原理是:鏈表實現(xiàn),其內存地址是不連續(xù)的。

  優(yōu)點:相對于數(shù)組,增加元素快;

  缺點;由于內存地址不連續(xù),查找性能低。

  8、集合與數(shù)組有什么區(qū)別?

  相同點:數(shù)組和集合都是容器

  數(shù)組和集合中存放的都是【對象的引用】而非對象本身

  不同點:數(shù)組存儲【基本數(shù)據(jù)類型】,是單一的。而且一旦聲明好長度后,長度不可變;

  集合【只能】儲存【對象】,但是可以是任意類型的對象,其長度可變。

  【集合的分類】

  ----|Iterable:接口

  Iterator iterator()

  ----|Collection:單列集合

  ----|List: 有序存儲順序,可重復

  ----|ArrayList: 數(shù)組實現(xiàn),查找快、增刪慢

  由于是數(shù)組實現(xiàn),在增和刪的時候會牽扯到數(shù)組增容,以及拷貝元素,所以慢;

  數(shù)組是可以直接按索引查找的,所以查找時比較快。

  ----|LinkedList: 鏈表實現(xiàn),增刪快、查找慢

  由于鏈表實現(xiàn),增加時只要讓前一個元素記住自己就可以了,刪除時讓前一個元

  素記住后一個元素,后一個元素記住前一個元素,這樣的增刪效率高;

  但查詢時需要一個一個的遍歷,所以效率比較低。

  ----|Vector: 多線程安全、效率略低 【ArrayList單線程效率高,但是多線程要使用Vector】

  ----|set: 無序存儲,不可重復

  ----|HashSet 線程不安全,存取速度快

  底層是以hash表實現(xiàn)的

  ----|TreeSet 紅-黑樹的數(shù)據(jù)結構,默認對元素進行自然排序(String)

  【TreeSet自身具備排序功能】

  ----|Comparable

  ----|compareTo(Object o) 元素自身具備比較性

  ----|Comparator

  ----|compare(Object o1,Object o2) 給容器傳入比較器

  如果在比較的時候兩個對象返回值是【0】,那么這兩個元素【重復】

  【當Comparable和Comparator比較方式同時存在時,以Comparator比較方式為主】

  ----|LinkedHashSet 會保存插入的順序

  ----|Map: 將鍵映射到值的對象。一個映射不能包含重復的鍵,每個鍵最多只能映射一個值。

  interface Map

  ----|TreeMap 底層是二叉樹數(shù)據(jù)結構,可以對map集合中的鍵進行排序

  需要使用Comparable或者Comparator進行比較排序。

  【return 0 判斷鍵的唯一性】

  ----|HashTable 底層是哈希表數(shù)據(jù)結構,線程是【同步】的 -->> 不可以存入null鍵、null值

  效率較低,故被【HashMap】替代

  ----|HashMap 采用哈希表實現(xiàn) -->> 【無序】

  底層是哈希表數(shù)據(jù)結構,線程是【不同步】的 -->> 可以存入null鍵、null值

  【要保證鍵的唯一性,需要覆蓋hashCode()方法和equals()方法】

  ----|LinkedHashMap

  【常用方法:】

  添加: V put(K key,V value) 可以是相同的key值,但是添加的value值會覆蓋前面的

  putAll(Map m)

  從指定映射中將所有映射關系復制到此映射中(可選操作)

  刪除: remove(Object key) 刪除關聯(lián)對象,指定key對象

  clear() 清空集合對象

  獲?。?value get(Object key) 可以用于判斷鍵是否存在的情況。

  判斷: boolean isEmpty() 如果此映射不包含鍵-值映射關系【即長度為0】,則返回true,否則返回false

  boolean containsKey(Object key)

  判斷集合中是否包含指定的key

  boolean containsValue(Object value)

  判斷集合中是否包含指定的value

  當指定的鍵不存在的時候,返回的是null

  長度: int size() 返回此映射中的鍵-值映射關系數(shù)

  9、在什么時候該使用什么樣的集合?

  Collection 當我們需要保存若干個對象的時候使用集合

  -->> List 如果需要保留存儲順序、并且重復元素時,使用List

  -->> 如果查詢較多,使用ArrayList;

  如果存取較多,使用LinkedList;

  如果需要線程安全,使用Vector。

  -->> Set 如果不需要保留存儲順序,并且要去掉重復元素時,使用Set

  -->> 如果需要將元素排序,使用TreeSet;

  如果不需要排序,使用HashSet 【HashSet比TreeSet效率高】

  如果需要保留存儲順序,同時要過濾重復元素,使用LinkedHashSet。

  10、自定義對象時為什么要重寫toString()和equals()方法?

  因為Object是自定義類的父類,Object類中的toString()方法返回的是哈希值;

  Object類中的equals()方法比較的是對象的地址值。

  【去除集合中重復的元素】

  代碼如下:

  public class Demo{

  public static void main(String[] args){

  ArrayList arr = new ArrayList();

  Person p1 = new Person("jack",20);

  Person p2 = new Person("rose",18);

  Person p3 = new Person("rose",18);

  arr.add(p1);

  arr.add(p2);

  arr.add(p3);

  System.out.println(arr);

  ArrayList arr2 = new ArrayList();

  for(int i=0;i<arr.size();i++){< p="">

  Object obj = arr.get(i);

  Person p = (Person)obj;

  if(!arr2.contains(p)){

  arr2.add(p);

  }

  }

  System.out.println(arr2);

  }

  }

  class Person{

  private String name;

  private int age;

  public Person(){

  }

  public Person(String name,int age){

  this.name = name;

  this.age = age;

  }

  public String getName(){

  return name;

  }

  public void setName(String name){

  this.name = name;

  }

  public int getAge(){

  return age;

  }

  public void setAge(int age){

  this.age = age;

  }

  public int hashcode(){

  return this.name.hashCode() + age*37;

  }

  public boolean equals(Object obj){

  if(!(obj instanceof Person)){

  return false;

  }

  Person p = (Person)obj;

  return this.name.equals(p.name) && this.age = p.age;

  }

  public String toString(){

  return "name:" + this.name + "age:" + this.age;

  }

  }

  11、Vector: 多線程安全、但是效率低 ---->> 描述的是一個線程安全的ArrayList。

  特有的方法:

  void addElement(E obj) 在集合末尾添加元素

  E elementAt(int index) 返回指定角標的元素

  Enumeration element() 返回集合中的所有元素,封裝到Enumeration對象中

  Enumeration接口:

  boolean hasMoreElements() 測試此枚舉是否包含更多的元素

  E nextElement() 如果此枚舉對象至少還有一個可提供的元素,則返回此枚舉的下一個元素

  【代碼如下:】

  public static void main(String[] args){

  Vector v = new Vector();

  v.addElement("aaa");

  v.addElement("bbb");

  v.addElement("ccc");

  // System.out.println(v.elementAt(2));

  Enumeration ens = v.elements();

  while(ens.hasMorreElements()){

  System.out.println(ens.nextElement());

  }

  }

  12、Iterable: 是Collection的父接口,實現(xiàn)Iterable的類可以進行迭代,并且支持增強for循環(huán)

  該接口只有一個方法,用于返回集合迭代器對象! 【獲取迭代器的方法iterator()】

  piblic interface Iterable

  Iteratoriterator():該類主要用于遍歷集合對象,并描述了遍歷集合的常見方法

  boolean hasNext() 判斷集合中是否有元素,如果有元素可以迭代,就返回true。

  E next() 返回迭代的下一個元素。

  如果沒有下一個元素,調用next()會拋出 -->> NoSuchElementException

  void remove() 從迭代器指向的集合中移除迭代器返回的最后一個元素

  【Iterator的for循環(huán)、清空】

  public class Demo{

  ArrayList list = new ArrayList();

  // 增加:add() 將指定對象存儲到容器中

  list.add("計算機網(wǎng)絡");

  list.add("現(xiàn)代操作系統(tǒng)");

  list.add("java編程思想");

  list.add("java核心技術");

  list.add("java語言程序設計");

  System.out.println(list);

  for(Iterator it = list.iterator();it.hasNext();){

  // 迭代器的next()方法返回值類型是Object,所有要記得【類型強轉】

  String next = (String)it.next();

  System.out.println(next);

  it.remove();

  }

  }

  【細節(jié)一:如果迭代器的指針已經指向了集合的末尾,那么如果再調用next()會返回NoSuchElementException異?!?/p>

  【細節(jié)二:如果調用remove()之前沒有調用next()方法是不合法的,會拋出IllegalStateException異?!?/p>

  【細節(jié)三:當一個集合在循環(huán)中即使用引用變量操作集合,又使用迭代器操作集合對象,會拋出ConcurrentModificationException異?!?/p>

  13、為什么next()方法的返回值類型是Object呢?

  為了可以接收任意類型的對象

  如果返回的時候不知道是什么類型的,就定義為object

  14、Iterator和ListIterator有什么關系?

  ListIterator是Iterator的子接口,是List集合特有的迭代器。

  Iterator在迭代時,只能對元素進行獲取【next()】和刪除【remove()】的操作;

  ListIterator在迭代list集合時,還可以對元素進行添加【add(obj)】和修改【set(obj)】的操作。

  15、List集合特有的迭代器ListIterator

  ---->> public interface ListIterator extends Iterator

  ListIteratorlistIteraotr()

  ----| Iterator

  hasNext()

  next()

  remove()

  ----| ListIterator

  add(E e) 將指定的元素插入列表(可選操作)。

  該元素直接插入到next()返回的下一個元素的前面(如果有)

  void set(E o) 用指定的元素替換next()或previous()返回的 【最后】 一個元素

  hasPrevious() 逆向遍歷列表,列表迭代器有多個元素,則返回true

  previous() 返回列表中的前一個元素

  16、HashSet是如何判斷兩個元素重復的?

  通過hashCode()方法和equals()方法來保證元素的唯一性,add()方法返回的是boolean類型

  【調用原理:HashSet集合在判斷元素是否相同,先判斷hashCode()方法,相同才會判斷equals()方法;不相同不會調用equals()】

  17、HashSet和ArrayList集合在判斷元素時是否有相同的方法?

  有:boolean contains(Object o)

  HashSet使用hashCode()和equals()方法,ArrayList使用eqauls()方法。

  18、給TreeSet指定排序規(guī)則:

  方式一:【元素自身】具備比較性

  元素自身具備比較性,需要元素實現(xiàn)【Comparable接口】,重寫【compareTo方法】,

  也就是讓元素自身具備比較性,這種方式叫做元素的【自然排序】也叫做【默認排序】。

  方式二:【容器】具備比較性

  當元素自身不具備比較性,或者自身具備的比較性不是所需要的。

  那么此時可以讓容器自身具備。需要定義一個類實現(xiàn)【Comparator接口】,重寫【compare方法】,

  并將該接口的子類實例對象作為參數(shù)傳遞給【TreeSet集合】的【構造方法】。

  注意:當Comparable比較方式和Comparator比較方式同時存在時,以【Comparator】的比較方式為主;

  注意:在重寫compareTo或者compare方法時,必須要明確比較的主要條件相等時要比較次要條件。

  通過return 0 來判斷唯一性。

  19、為什么使用TreeSet存入字符串,字符串默認輸出是按升序排列的?

  因為字符串實現(xiàn)了一個接口,叫做【Comparable接口】,字符串重寫了該接口的【compareTo()方法】,

  所以String對象具備了比較性。

  【自定義的元素(比如Person類、Book類)想要存入TreeSet集合,就必須實現(xiàn)Comparable接口,也就是要讓自定義對象具備比較性】

  【存入TreeSet集合的元素都要具備比較性:要實現(xiàn)Comparable接口、并重寫該接口的compareTo()方法】

  20、總結:

  看到array,就要想到角標。

  看到link, 就要想到first,last。

  看到hash, 就要想到hashCode,equals.

  看到tree, 就要想到兩個接口。Comparable,Comparator。

  21、TreeSet是如何保證元素的唯一性的?

  通過【compareTo】或者【compare】方法來保證元素的唯一性。

  當Comparable接口中的compareTo()函數(shù)返回值為【0】時,說明兩個對象相等,此時該對象不會被添加進來。

  22、使用TreeSet集合將字符串 String str = "8 10 15 5 2 7"; 的數(shù)值進行排序。

  public class Demo{

  public static void main(String[] args){

  String str = "8 10 15 5 2 7";

  String strs = str.split(" ");

  TreeSet ts = new TreeSet();

  for(int x= 0;x<strs.length();x++){< p="">

  int y = Integer.parseInt(strs[x]);

  ts.add(y);

  }

  System.out.println(ts);

  }

  }

  23、遍歷Map集合的方式有哪些?

  方式一:使用keySet

  將Map轉成Set集合【keySet()】,通過Set的迭代器【Iterator】取出Set集合中的每一個元素,

  即Map集合中所有的鍵,再通過get()方法獲取鍵對應的值

  Setks = map.keySet();

  Iteratorit = ks.iterator();

  while(it.hasNext()){

  Integer key = it.next();

  String value = map.get(key);

  }

  方式二:通過values獲取所有值,但是不能獲取到key對象

  Collectionvs = map.values();

  Iteratorit = vs.iterator();

  while(it.hasNext()){

  String value = it.next();

  }

  方式三:Map.Entry -->> public static interface Map.Entry

  通過Map中的entrySet()方法獲取存放Map.Entry對象的Set集合 -->> Set<map.entry> entrySet()

  Set<map.entry> entrySet = map.entrySet();

  Iterator<map.entry> it = entrySet.iterator();

  while(it.hasNext()){

  Map.Entryen = it.next();

  }

  Integer key = en.getKey();

  String value = en.getValue();



作者:黑馬程序員JavaEE培訓學院

首發(fā): http://java.itheima.com

分享到:
在線咨詢 我要報名
和我們在線交談!