Java Collections Framework是Java提供的对集合进行定义,操做,和管理的包含一组接口,类的体系结构。php
Java集合框架的基本接口/类层次结构:html
java.util.Collection [I] +--java.util.List [I] +--java.util.ArrayList [C] +--java.util.LinkedList [C] +--java.util.Vector [C] +--java.util.Stack [C] +--java.util.Set [I] +--java.util.HashSet [C] +--java.util.SortedSet [I] +--java.util.TreeSet [C] java.util.Map [I] +--java.util.SortedMap [I] +--java.util.TreeMap [C] +--java.util.Hashtable [C] +--java.util.HashMap [C] +--java.util.LinkedHashMap [C] +--java.util.WeakHashMap [C]
其中I表示接口,C表示实现类java
在实际开发中,须要将使用的对象存储于特定数据结构的容器中。JDK提供了这样的容器---集合(Collection)。Collection是一个接口,定义了集合相关的操做方法,其有两个子接口:List与Setc++
List:可重复集合 Set:不可重复的集合 其中判断元素是否重复,取决于元素的equals()比较的结果
集合中存储的都是引用类型元素,而且集合只保存每一个元素对象的引用,而并不是将元素对象自己存入集合。objective-c
Collection定义了一个add方法用于向集合中添加新元素。 boolean add(E e) 该方法返会将给定的元素添加进集合,若添加成功,则返回true,不然返回false。
实例1c#
import java.util.ArrayList; import java.util.Collection; public class Test00{ public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c); c.add("a"); c.add("b"); c.add("c"); System.out.println(c); } }
boolean contains(Object o) 该方法用于断定给定的元素是否被包含在集合中。若包含则返回true,反则返回false。 注意:集合在判断元素是否被包含在集合中是根据每一个元素的equals方法进行比较的结果。 一般有必要重写equals()保证contains()方法的合理结果
实例2:数组
import java.util.ArrayList; import java.util.Collection; public class Test00{ public static void main(String[] args) { Collection<String> c = new ArrayList<String>(); System.out.println(c); c.add("a"); c.add("b"); c.add("c"); System.out.println(c); Collection<String> b = new ArrayList<String>(); b.add("b"); b.add("c"); System.out.println(c.contains(b)); System.out.println(c.contains("b")); c.addAll(b); System.out.println(c); System.out.println(c.contains(b)); System.out.println(c.contains("h")); } }
int size() 该方法用于返回当前集合中的元素总数 void clear() 该方法用于清空当前集合。 boolean isEmpty() 该方法用于断定当前集合中是否不包含任何元素
实例3 :数据结构
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); System.out.println(c.isEmpty()); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("cpp"); System.out.println("isEmpty : " + c.isEmpty() + ",size : "+ c.size()); c.clear();// 清空该集合 System.out.println("isEmpty : "+ c.isEmpty() + ",size : " + c.size()); } } addAll containsAll boolean addAll(Collection <? extends E> c) 该方法须要咱们传入一个集合,并将该集合中的全部元素添加到当前集合中。 boolean containsAll(Collection<?> c) 该方法用于断定当前结合是否包含给定集合中的全部元素,若包含则返回true。
实例4并发
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class Test00{ public static void main(String[] args) { Collection<String> c1 = new ArrayList<String>(); c1.add("java"); c1.add("cpp"); c1.add("php"); c1.add("c#"); c1.add("objective-c"); c1.add("cppc"); System.out.println(c1); Collection<String> c2 = new HashSet<String>(); c2.addAll(c1); System.out.println(c2); Collection<String> c3 =new ArrayList<String>(); c3.add("java"); c3.add("cpp"); System.out.println(c1.containsAll(c3)); } }
Iterator是迭代器,拥有两个方法框架
迭代器用于遍历集合元素。获取迭代器可使用Collection定义的方法:
Iterator iterator()
迭代器Iterator是一个借口,集合在重写Collection的iterator()方法时利用内部类提供了迭代器的实现。 Iterator提供了统一的遍历元素集合的方法,其提供了用于遍历集合的两个方法: boolean hasNext():判断集合是否还有元素能够遍历 E next():返回迭代的下一个元素
实例4
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); Iterator<String> iterator = c.iterator(); while(iterator.hasNext()){ String str = iterator.next(); System.out.println(str); } } }
在使用迭代器遍历集合时,不能经过集合的remove方法删除集合元素,不然会抛出并发更改异常。咱们能够经过迭代器自身提供的remove()方法来删除经过next()迭代出的元素
void remove()
迭代器的删除方法是在原集合中删除元素。
这里须要注意的是:在调用remove方法前必须经过迭代器的next方法迭代过的元素,那么删除的就是这个元素。而且不可以再次调用remove方法,除非再次调用next()后方可再次调用。
实例5:
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); Iterator<String> it = c.iterator(); while(it.hasNext()){ String str = it.next(); if(str.indexOf("c")!=-1){ it.remove();// 删除包含字母c的元素 } } System.out.println(c); } }
Java5.0以后推出了一个新的特性,加强for循环,也成为新循环。该循环不通用于传统循环的工做,其只用于遍历集合或数组。
语法: for(元素类型 e:集合或数组){ 循环体 }
实例7
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test00{ public static void main(String[] args) { Collection<String> c = new HashSet<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); for(String str : c) { System.out.print(str.toUpperCase()+" "); //C# CPP OBJECTIVE-C JAVA PHP } } }
新循环并不是新的语法,而是在编译过程当中,编译器会将新循环转为迭代器模式。因此新循环本质上是迭代器。
泛型是Java SE5.0引入的特性,泛型的本质是参数化类型。在类、接口、和方法的定义过程当中,所操做的数据类型被传入的参数指定。
Java泛型机制普遍的应用在集合框架中。全部的集合类型都带有泛型的参数,这样在建立集合时能够指定放入集合中的元素的类型。Java编译器能够据此进行类型检查,这样能够减小代码在运行时出现错误的可能性。
List接口是Collection的子接口,用于定义线性表数据结构。能够讲List理解为存放对象的数组,只不过其元素能够动态的增长或减小。
List接口的两个常见实现类为ArrayList和LinkList,分别用动态数组和链表的方式实现了List接口。
能够认为ArrayList和LinkedList的方法在逻辑上彻底同样,只是在性能上有必定差异。ArrayList更适合于随机访问,LinkList更适合于插入和删除。在性能要求不是特别苛刻的情形下能够忽略这个差异。
List除了继承Collection定义方法外,还根据其线性表的数据结构定义了一系列的方法,其中最经常使用的就是基于下标的get和set方法
E get(int index) 获取集合执行下标对应的元素,下标从0开始。 E set(int index,Element) 将给定的元素存入给定位置,并将原位置的元素返回。
实例8
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; public class Test00{ public static void main(String[] args) { List<String> c = new ArrayList<String>(); c.add("java"); c.add("cpp"); c.add("php"); c.add("c#"); c.add("objective-c"); for(int i = 0;i<c.size();i++){ System.out.println(c.get(i).toUpperCase()); } String value = c.set(1, "c++"); System.out.println(value);// cpp System.out.println(c);// [java, c++, php, c#, objective-c] c.set(1,c.set(3, c.get(1)));// 交换1和3上的元素位置 由于内层返回的是3位置的元素 System.out.println(c);// [java, c#, php, c++, objective-c] } }
List根据下标的操做还支持插入语删除操做
void add(int index,Element);
将给定的元素插入到指定位置,原位置及后续元素都顺序向后移动。
E remove(int index);
删除给定位置的元素,并将被删除的元素返回。
List的toArray方法用于将集合转换为数组。但实际上该方法是在Collection中定义的,因此全部的集合都具有这个功能。
其有两个方法: Object[] toArray() <T>T[] toArray(T[] a)
其中第二个方法是比较经常使用的,咱们能够传入一个指定类型的数组,该数组的元素类型与集合的元素类型一致。返回值则是转换后的数组,该数组会保存集合中的全部元素。
Arrays类中提供了一个静态方法asList,使用该方法咱们能够将一个数组转换为对应的List集合。
其方法定义为:
static <T>List<T> asList<T... a>
返回的List的集合元素类型由传入的数组的元素类型决定。
而且要注意的是,返回的集合咱们不能对其增删元素。而且对集合的元素进行修改hi影响数组对应的元素。
Collection.sort方法实现排序
Collection是集合的工具类,它提供了不少便于咱们操做集合的方法,其中就有用于集合排序的sort方法。该方法定义为:
void sort(List<T> list) 该方法的做用是对给定的集合元素进行天然排序。
Collection的sort方法是对集合元素进行天然排序,那么两个元素对象之间就必定要有大小之分。这个代销之分是如何界定的?
实际上,在使用Collection的sort排序的结合都必须是Comparable接口实现类,该接口表示其子类是可比较的,由于实现该接口必须重写抽象方法:
int compareTo(T t); 该方法返回值要求: 若o1>o2则返回值应>0 若o1<o2则返回值应<0 若o1=o2则返回值由于0
双向链表 双端效率高
方法
add(数据) 添加数据 get(i) 访问指定位置的收 remove(i) 移除指定位置的数据 size() 元素的数量 addFirst() 在链表首处添加元素 addLast() 在链表末尾添加元素 getFirst() 得到第一个元素 getLast() 得到末尾元素 removeFirst() 删除第一个元素 removeLast() 删除最后一个元素 iterator() 辅助建立迭代器对象进行设置
LinkedList实例:
import java.lang.reflect.Array; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; public class Test00{ public static void main(String[] args) { LinkedList<String> list = new LinkedList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); list.add("eee"); list.add("fff"); list.add("ggg"); list.add("hhh"); list.add("iii"); list.add("jjj"); list.add("kkk"); list.add("lll"); System.out.println("获取链表数组的大小: "+list.size());// 获取链表的大小 System.out.println("get方法获取元素 "+list.get(0)); System.out.println("获取第一个元素"+list.getFirst()); System.out.println("获取链表的以后一个元素 "+list.getLast()); LinkedList<String> list1 = new LinkedList<>(); list1.addAll(list); for(String s1:list1){// 元素遍历 System.out.println(s1); } // 经过迭代器来遍历 Iterator<String> iterator = list.iterator(); if(iterator.hasNext()){ String str = iterator.next(); System.out.println(str); } System.out.println("删除链表的第一个元素 "+list.removeFirst()); System.out.println("删除链表的最后一个元素: "+list.removeLast()); System.out.println("找到第一个相等的元素进行删除 "+list.remove("ddd")); System.out.println("指定删除链表中的某个元素:"+list.remove(4)); System.out.println(list.toArray());// 将list链表转为数组 Object[] listarr = list.toArray();// 将list转为数组,并利用数组的方式进行答应 System.out.println(Arrays.toString(listarr)); } }
6.8 ArrayList和LinkedList的大体区别以下:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于随机访问get和set,ArrayList以为优于LinkedList,由于LinkedList要移动指针。 3.对于新增和删除操做add和remove,LinedList比较占优点,由于ArrayList要移动数据
示例以下:
import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; public class Test00{ static final int N = 500000; static long timeList(List list){ long start = System.currentTimeMillis(); Object o = new Object(); for(int i = 0;i<N;i++){ list.add(0,o); } return System.currentTimeMillis() - start; } static long readList(List list){ long start = System.currentTimeMillis(); for(int i = 0;i<list.size();i++){ } return System.currentTimeMillis() - start; } static List addList(List list){ Object o = new Object(); for(int i = 0;i<N;i++){ list.add(0,o); } return list; } public static void main(String[] args) { System.out.println("ArrayList添加"+N+"条耗时:"+timeList(new ArrayList())); System.out.println("LinkedList添加"+N+"条耗时"+timeList(new LinkedList())); List list1 = addList(new ArrayList()); List list2 = addList(new LinkedList()); System.out.println("ArrayList查找"+N+"条耗时"+readList(list1)); System.out.println("LinkedList查找"+N+"条记录耗时"+timeList(list2)); /* 结果以下 ArrayList添加500000条耗时:31141 LinkedList添加500000条耗时1 ArrayList查找500000条耗时15 LinkedList查找500000条记录耗时3 */ } }
队列是经常使用的数据结构,能够将队列当作特殊的线性表,队列限制了线性表的访问方式:只能从线性表 的一端添加(offer)元素,从另外一端取出(poll)元素。 队列遵循先进先出(FIFO First Input First Output)的原则。 JDK中提供了Queue接口,同时使用LinkedList实现了该接口(选择LinkList实现Queue的缘由在于 Queue常常要进行添加和删除的操做,而LinkList在这方面效率较高)。
Queue接口中主要方法以下:
boolean off(E e) 将一个元素添加至队尾,若是添加成功则返回true。 E poll() 从队首删除并返回一个元素。 E peek() 返回队首的元素(但并不删除).
Deque是Queue的子接口,定义了所谓的"双端队列",即从队列的两端分别能够入队(offer)和出队(poll),LinkList实现了该接口。
若是将Deque限制为只能从一端入队和出队,则可实现"栈"(Stack)数据结构,对栈而言,入栈称之为push,出栈称之为pop。
栈遵循先进后出(FILO First Input Last Output)的原则。
import java.util.LinkedList; import java.util.Queue; public class Test00{ public static void main(String[] args) { Queue<String> queue = new LinkedList<String>(); queue.offer("a");// 将一个对象添加至队尾,若是添加成功则返回true queue.offer("b"); queue.offer("c"); System.out.println(queue); String str =queue.peek(); System.out.println(str); while(queue.size()>0){ // 从队首删除并返回一个元素 str = queue.poll(); System.out.println(str + " "); } } }