9.1 Java集合框架
9.1.1 集合接口与实现分离
1、Java集合类库将接口(interface)与实现(implementation)分离。
2、队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数。
队列通常有两种实现方式:一种是使用循环数组;另一种是使用链表。
9.1.2 Collection接口
2个基本方法:
- add:用于向集合中添加元素
boolean add(E element);
- iterator:用于返回一个实现了Iterator接口的对象
Iterator<E>iterator();
9.1.3 迭代器
4个方法:
public interface Iterator<E> { E next(); boolean hasNext(); void remove(); default void forEachRemaining(Consumer<? super E> action); }
Java迭代器位于两个元素之间,当调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的调用。
next方法和removew方法调用之间存在依赖性。如果调用remove之前没有调用newxt,将是不合法的。
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorDemo2 { public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); c.add("jwoevhoweh"); c.add("888888"); c.add("wuge"); c.add("yueyue"); // 迭代器循环输出 System.out.println("删除之前:"); Iterator<String> iter = c.iterator(); while (iter.hasNext()){ String str = iter.next(); System.out.print(str+" "); } iter.remove(); iter.remove(); System.out.println(); System.out.println("删除之后"); // foreach循环输出 for (String x :c){ System.out.print(x+" "); } } }
运行时抛出异常:
删除之前: jwoevhoweh 888888 wuge yueyue Exception in thread "main" java.lang.IllegalStateException at java.util.ArrayList$Itr.remove(ArrayList.java:872) at com.hengqin.test1.IteratorDemo2.main(IteratorDemo2.java:22) Process finished with exit code 1
改为:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorDemo2 { public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); c.add("jwoevhoweh"); c.add("888888"); c.add("wuge"); c.add("yueyue"); System.out.println("删除之前:"+c); Iterator<String> iter = c.iterator(); iter.next(); iter.remove(); iter.next(); iter.remove(); System.out.println("删除之后:"+c); } }
9.2 集合框架中的接口
集合有两个基本接口:Collection和Map。
可以用以下方法在集合中插入元素:boolean add(E element)
不过,由于映射包含键/值对,所以要用put来插入: V put(Key, V value)
要从集合中读取元素,可以用迭代器访问元素。不过,从映射中读取值则要使用get方法:V get(K key)
List是一个有序集合,使用迭代器访问时,必须顺序地访问元素。
import java.util.ArrayList; import java.util.List; public class ListDemo1 { public static void main(String[] args) { List<String> list = new ArrayList<String>(); //增加元素 list.add(0,"jiayou"); list.add(1,"jiayou"); list.add(2,"xuexi"); list.add(3,"shiwo"); list.add(4,"kuaile"); System.out.println("添加完之后:"+list); //删除元素 list.remove(2); list.remove(1); System.out.println("删除元素之后:"+list); //获取数据 System.out.println(list.get(1)); System.out.println(list.get(2)); //设置数据,可用来修改数据 list.set(0,"xuexi"); //list.set(4,"jiayou"); // IndexOutOfBoundsException System.out.println(list); } }
运行结果:
添加完之后:[jiayou, jiayou, xuexi, shiwo, kuaile]
删除元素之后:[jiayou, shiwo, kuaile]
shiwo
kuaile
[xuexi, shiwo, kuaile]
9.3 具体集合
9.3.1 链表
数组是在连续的存储位置上存放对象引用,而链表则是将每个对象存放在单独的链接(link)中,每个链接还存放着序列中下一个链接的引用。
public class LinkedListDemo1 { public static void main(String[] args) { LinkedList<String> list = new LinkedList<String>(); list.add(0,"1"); list.add("Amy"); list.add("Bob"); list.add(1,"2"); list.add("Carl"); list.addFirst("djwojc"); System.out.println(list); Iterator<String> iter = list.iterator(); iter.next(); iter.next(); iter.remove(); list.removeLast(); System.out.println(list); ListIterator<String> iter2 = list.listIterator(); iter2.next(); iter2.add("2"); System.out.println(list); while (iter2.hasPrevious()){ String str = iter2.previous(); System.out.print(str+" "); } } }
运行结果:
[djwojc, 1, 2, Amy, Bob, Carl]
[djwojc, 2, Amy, Bob]
[djwojc, 2, 2, Amy, Bob]
2 djwojc
9.3.2 数组列表
ArraryList 封装了一个动态再分配的对象数组。
9.3.3 散列集
散列表(hash table)为每个对象计算一个整数,称为散列码。
import java.util.HashSet; import java.util.Iterator; import java.util.Scanner; import java.util.Set; public class SetDemo2 { public static void main(String[] args) { Set <String> hs = new HashSet<String>(); long totaltime = 0; for (int x = 0;x<10;x++){ Scanner in = new Scanner(System.in); String word = in.next(); long calltime = System.currentTimeMillis(); hs.add(word); calltime = System.currentTimeMillis() - calltime; totaltime+=calltime; } Iterator<String> iter = hs.iterator(); for (int i = 1; i<=10 && iter.hasNext();i++){ System.out.print(iter.next()+" "); } System.out.println(hs.size()+ " distinct words."+totaltime+" milliseconds"); } }
a
v
dqw
ew
1
1
2
2
a
l
a 1 ew 2 v dqw l
7 distinct words.0 milliseconds
9.3.4 树集
要使用树集,必须能够比较元素。这些元素必须实现Comparable接口,或者构造集时必须提供一个Comparator
import java.util.Comparator; import java.util.Objects; import java.util.Set; import java.util.TreeSet; public class TreeSetDemo1 { public static void main(String[] args) { Set<Item1> parts = new TreeSet<Item1>(); parts.add(new Item1(1234,"Toaster")); parts.add(new Item1(4562,"Widget")); parts.add(new Item1(9921,"Modem")); System.out.println(parts); Set sortByDescription = new TreeSet<Item1>(Comparator.comparing(Item1::getDescription)); sortByDescription.addAll(parts); System.out.println(sortByDescription); } }
import java.util.Objects; public class Item1 implements Comparable<Item1>{ private int iid; private String description; public Item1(int iid,String description){ this.iid = iid; this.description = description; } public String getDescription(){ return this.description; } public String toString(){ return "[description="+this.description+",partiid="+this.iid+"]"; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; com.hengqin.test1.Item1 item1 = (com.hengqin.test1.Item1) o; return iid == item1.iid && Objects.equals(description, item1.description); } @Override public int hashCode() { return Objects.hash(iid, description); } public int compareTo(com.hengqin.test1.Item1 other){ int diff = Integer.compare(iid,other.iid); return diff != 0 ? diff:description.compareTo(other.description); } }
运行结果
[[description=Toaster,partiid=1234], [description=Widget,partiid=4562], [description=Modem,partiid=9921]]
[[description=Modem,partiid=9921], [description=Toaster,partiid=1234], [description=Widget,partiid=4562]]