黑马程序员——Java基础(七)之集合

-----------android培训、java培训、java学习型技术博客、期待与您交流!------------

集合概述:

是一个可以存储多种元素的容器。

集合的特点:

集合的长度可变,只能存储对象,但对象类型可以不同。

集合与数组的区别:

数组的长度固定,能存储基本数据类型和引用数据类型,但一个数组只能存储同一种数据类型。

集合体系的继承体系结构图:


Collection<E>接口(java.util包)

概述:是集合的顶层接口,Collection表示一组对象,这些对象也称为Collection的元素。

成员方法

添加功能的方法:

boolean add(E e);

     添加元素。

boolean addAll(Collection<E> c);

     添加一个集合的元素。

删除功能:

void clear();

     移除所有元素。

boolean remove(Object o);

     移除一个元素。

boolean removeAll(Collection c);

     移除一个集合的元素。

判断功能:

boolean contains(Object o);

     判断集合中是否包含指定元素。

boolean containsAll(Collection<?> c);

     判断集合中是否包含(包含所有)指定的集合元素。

boolena isEmpty();

     判断集合是否为空。(有无元素)

获取功能:

Iterator<E> iterator();

     返回在此collection的元素上进行迭代的迭代器。

交集功能:

boolean retainAll(Collection c);

     调用者将只保留两个集合相交的元素,返回的boolean值表示调用者的元素是否发生了改变。

长度功能:

int size();

     返回集合的长度。

转换功能:

Object[] toArray();

     把集合转为数组。


Iterator<E>接口(Java.util包)

概述:对Collection进行迭代的迭代器,它是遍历集合的一种方式。

成员方法:

boolean hasNext();

     若仍有元素迭代,返回true。

E next();

     获取元素,并移动到集合中下一个位置。

使用迭代器Iterator遍历集合的步骤:

a:通过集合的iterator()方法获取迭代器对象;

b:通过迭代器中的hasNext()方法判断是否有元素;

c:通过迭代器中的next()方法获取元素。


List<E>接口(java.util包)

概述:此接口是Collection的子接口,特点为有序,可重复。

成员方法:

void add(int index,Object element);

     在指定索引位置添加元素。

E get(int index);

     获取指定位置的元素。

int indexOf(Object o);

     获取指定元素在集合中首次出现的索引,如果没有该元素,返回-1。

ListIterator listIterator();

     List集合特有的迭代器。

E remove(int index);

     根据索引删除元素,返回被删除的元素。

E set(int index,E element);

     根据索引修改元素,返回被修改的元素。

List<E> subList(int fromindex,int toindex);

     截取元素。


ListIterator<E>接口(java.util包)

概述:此接口是Iterator的子接口,具有逆序遍历的特有功能。

boolean hasPrevious();

     逆向遍历的判断,若上一位置仍有元素迭代,则返回true。

E previous();

     获取上一个元素。


ConcurrentModificationException

并发修改异常:当迭代器遍历元素时,通过集合修改元素会出现此异常,要避免此异常,有两种方法:

a:迭代器遍历元素时,可通过迭代器修改元素;

b:使用集合遍历元素时,可通过集合修改元素;


常见数据结构的特点

栈:先进后出;

队列:先进先出;

数组:查询块,增删慢;

链表:查询慢,增删块;

List接口三个实现类的特点:

ArrayList:底层数据结构是数组,查询块,增删慢,线程不安全,效率高;

Vector:底层数据结构是数组,查询块,增删慢,线程安全,效率低;

LinkedList:底层数据结构是链表,查询慢,增删块,线程不安全,效率高;


Vector<E>类(java.util包)

概述:该类是List接口的具体实现类,它在List接口基础上有如下特殊功能。

构造方法:

public Vector();

     构造一个空集合,内部数据数组大小默认为10。

成员方法:

public void addElement(E obj);

     添加元素到集合的末尾,此方法与add()方法功能相同。

public E elementAt(int index);

     获取指定索引处的元素,此方法与get(int index)方法功能相同。

public Enumeration<E> element();

     返回此集合的枚举,此方法与List接口的迭代器方法类似。

Enumeration<E>接口(java.util包)

此接口与Iterator类似,可提供对Vector集合的迭代器遍历方法。

成员方法:

boolean hasMoreElenents();

     判断此枚举是否包含下一个元素,与Iterator中的hasNext()方法类似。

E nextElement();

     返回此枚举的下一个元素,与Iterator中的nextj()方法类似。


LinkedList<E>类(java.util包)

概述:该类是List接口的具体实现类,它在List接口基础上有如下特殊功能。

成员方法:

public void addFirst(E e);

     将指定元素添加到列表的开头。

public void addLast(E e);

     将指定元素添加到列表的结尾。

public E getFirst();

     返回此列表的第一个元素。

public E getLast();

     返回此列表的最后一个元素。

public E removeFirst();

     移除并返回此列表的第一个元素。

public E removeLast();

     移除并返回此列表的第一个元素。


泛型

概述:是一种把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊类型。一般多出现在集合中。

格式:

<数据类型>

这里的数据类型只能是引用类型。

使用泛型的好处:

a:把程序运行时的异常提前到了编译时期;

b:避免了强制类型转换。

泛型类:

带有泛型的类称为泛型类。

格式:

public class 类名<泛型类型1,...>

注意:泛型类型必须是引用类型。

泛型方法:

带有泛型的方法。

格式:

public <泛型类型> 返回类型 方法名(泛型类型)

泛型接口:

带有泛型的接口。

格式:

public interface 接口名<泛型类型>

其实现类格式:

public class 实现类名<泛型类型> implements 接口名<泛型类型>

泛型通配符的三种格式:

<?>   表示任意类型,如果没有明确,那么就是Object类型;

<? extends E>   向下限定,表示E及其子类型;

<? super E>   向上限定,表示E及其父类型;


增强for

概述:for循环的一种简化形式,用于简化数组和集合的遍历。

格式:

for(元素数据类型 变量 : 数组或集合名) {

变量即为该元素,直接使用即可

}

注意事项:增强for的目标要判断是否为null;增强for的底层其实是调用的Iterator接口。


静态导入

格式:

import static 报名....类名.方法名

导包为导入到类名,静态导入为导入到方法名。

注意事项:

a:方法必须为静态;

b:方法同名时,使用者要加前缀。


可变参数

概述:方法的参数类型为未知多个时,可定义参数为可变参数。

格式:

修饰符 返回值类型 方法名(数据类型... 变量名) {

方法体

}

注意事项:

a:这里的变量其实是一个数组;

b:如果一个方法有多个参数,可变参数必须在最后一个;

asList方法

Arrays类中的静态方法,格式为:

public static <T> List<T> asList(T... a);

     把数组转换为集合。

注意事项:

转换后的集合因为其本质是数组,所以长度固定,该集合不能使用能改变其长度的方法。


Set<E>接口(java.util包)

概述:此接口是Collection的子接口,但不同于List接口,实现此接口的集合特点为存储顺序和取出顺序不一定一致,且元素唯一。


HashSet<E>类(java.util包)

概述:此类是Set接口的具体实现类,它的底层数据结构是哈希表。

Set接口中元素唯一的原理:通过底层查看其添加方法add(),它的依赖两个方法hashCode()和equals(),具体添加元素步骤如下,

a:首先走hashCode()方法,比较哈希值;

b:如果哈希值相同,直接添加,如果不同,再比较两个元素的地址值或者它们的equals()方法;

c:当这两个值都为false时,说明这两元素为同一元素,即不执行添加操作;

当存储自定义对象时,要在自定义类中重写hashCode()和equals()方法,才能保证自定义对象的在集合中是唯一的。

LinkedHashSet<E>类(java.util包)

概述:此类是HashSet的子类。它的底层数据结构是哈希表和链表组成,哈希表保证其元素的唯一性,链表保证其元素的有序。


TreeSet<E>类(java.util包)

概述:它是Set接口的具体实现类。

它的特点是元素唯一,但其内部元素有序,因为它的底层结构是红黑数,使用了元素的自然顺序或者使用Comparator进行排序。

构造方法:

public TreeSet();

     构造一个新的空set集合对象,该集合根据其元素的自然顺序进行排序。

public TreeSet(Comparator<? super E> comparator);

     构造一个新的空TreeSet集合对象,它根据指定的比较器进行排序。

TreeSet集合中存储元素的两种方式:

a:使用自然排序方法存储,可使用TreeSet类的无参构造方法,让元素所属的类必须实现Comparable接口,并重写其CompareTo()方法。

b:使用比较器排序方法存储,使用带有比较器的构造方法,让构造方法接收一个比较器接口Comparator的实现类对象,通过该对象重写Comparator接口中的compare()方法,来实现比较器排序。


Comparable<T>接口(java.lang包)

概述:此接口强行对实现它的每个类的对象进行整体排序,这种排序叫自然排序。

成员方法:

int compareTo(T o);

     比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。


Comparator<T>接口(java.util包)

概述:此接口强行对某个集合进行整体排序,排序方式为比较器排序。

成员方法:

int compare(T o1,T o2);

     用来比较排序两个参数,根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

使用Comparator接口对集合排序举例:

<span style="font-size:14px;">//TreeSet集合存储自定义对象并使用比较器排序
public class TreeSetDemo {
	public static void main(String[] args) {
		Student s1 = new Student("张三",20);
		Student s2 = new Student("李四",21);
		Student s3 = new Student("王五",22);
		Student s4 = new Student("赵六",21);
		Student s5 = new Student("张三",20);
		Student s6 = new Student("张三",22);
		
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
			public int compare(Student s1, Student s2) {
				int num = s2.getAge()-s1.getAge();
				int num2 = num==0? s2.getName().compareTo(s1.getName()): num;
				return num2;
			}
		});
		
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		
		for(Student s : ts) {
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}
}</span>


Map<K,V>接口(java.util包)

概述:Map集合中存储的是键值对元素,即存储的元素是成对出现的,是将键映射到值的对象。集合中一个映射不能包含重复的键,每个键只能映射到一个值,其中键是唯一的,值是可重复的。Map集合的数据结构针对键有效,和值无关。

成员方法

添加功能:

V put(K key,V value);

     添加一个元素。(添加元素时,如果key不存在,则返回null,如果key存在,则返回原来该键所对应的值。)

void putAll(Map<? extends K, ? extends V> m);

     添加一个Map集合到此集合中。

删除功能:

void clear();

     移除所有键值对元素。

V remove(Object key);

     根据键删除元素,并返回其对应的值。

判断功能:

boolean containsKey(Object Key);

     判断集合是否包含指定的键。

boolean containsValue(Object Value);

     判断集合是否包含指定的值。

boolean isEmpty();

     判断集合是否为空。

获取功能:

Set<Map.Entry<K,V>> entrySet();

     获取所有键值对对象的集合。

V get(Object Key);

     根据键获取值。

Set<K> keySet();

     获取Map集合中所有键的集合。

Collection<V> values();

     获取Map集合中所有值的集合。

长度功能:

int size();

     返回集合的长度。


Map.Entry<K,V>接口(java.util包)

概述:表示Map集合的键值对,它有如下方法:

K getKey();

     返回此键值对对象的键。

V getValue();

     返回此键值对对象的键。

使用该接口可遍历Map集合,方法如下:

<span style="font-size:14px;">//有一个字符串"abcdeabcdabcaba",获取字符串中每一个字符出现的次数并输出,格式为"a(5)b(4)c(3)d(2)e(1)"
public class TreeMapDemo {
	public static void main(String[] args) {
		//键盘录入一个字符串
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入字符串");
		String StringIn = sc.nextLine();
		//定义一个TreeMap集合
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		//把字符串转换为字符数组
		char[] chs = StringIn.toCharArray();
		//遍历字符数组
		for(char ch : chs) {
			//判断集合中是否有该字符对应的键,如果有,集合的值加1,如果没有,直接添加该键
			if(!tm.containsKey(ch)) {
				tm.put(ch, 1);
			} else {
				Integer i = tm.get(ch);
				tm.put(ch,++i);
			}
		}
		//定义字符缓冲区变量
		StringBuilder sb = new StringBuilder();
		//获取Map集合中所有的键和值
		Set<Map.Entry<Character,Integer>> set = tm.entrySet();
		for(Map.Entry<Character,Integer> me : set) {
			Character ch = me.getKey();
			Integer it = me.getValue();
			//将键和值添加到字符缓冲区中
			sb.append(ch).append('(').append(it).append(')');
		}
		System.out.println(sb);
	}
}</span>


HashMap<K,V>类(java.util包)

概述:是基于哈希表的Map接口的实现类,其中哈希表的作用是用来保证键的唯一性的。

LinkedHashMap<K,V>类(java.util包)

概述:是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。其中哈希表保证键的唯一性,有链表保证键的有序性(存储和取出的顺序一致)。

TreeMap<K,V>类(java.util包)

概述:是基于红黑树的Map接口的实现,它的键是红黑树结构,用来保证键的有序和唯一。

Hashtable<K,V>类

概述:是基于哈希表的Map接口的实现类,和HashMap大致相同。

HashMap和Hashtable的区别:

HashMap:线程不安全,效率高,允许null键和null值。

Hashtable:线程安全,效率低,不允许null键和null值。


Collections类(java.util包)

概述:是针对集合进行操作的工具类。

成员方法:

public static <T> void sort(List<T> list);

     以元素的自然顺序对集合按升序排列。

public static <T> int binarySearch(List<T> list, T key);

     二分查找,将索引返回。

public static <T> T max(Collection<?> coll);

     返回集合中的最大值。

public static void reverse(List<?> list);

     对集合反转。

public static void shuffle(List<?> list);

     随机置换。

public static <T> void sort(List<T> list, Comparator<? super T> c);

     用比较器对集合中的元素排序。



版权声明:本文为Ghost_Train原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。