集合

一、概述

对象用于封装特有数据,对象多了需要存储。如果对象的个数不确定,就使用集合容器进行存储。其长度可变,不可以存储基本数据类型值。

1.集合框架

集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。如图为Collection的简化层次结构:
  

2.Colletion接口

Colletion接口常用方法:
  1) 添加: add, addAll
  2) 删除: remove, removeAll, clear
  3) 判断: contains, containsAll, isEmpty
  4) 获取: size, iterator
  迭代器(Iterator)是对所有的Collection容器进行元素取出的公共接口。
  Iterator iterator = iterable.iterator();
  iterator.hasNext(); iterator.next();
  5) 其他: retainAll, toArray

/* Collection常用方法示例*/
import java.util.*;
public class CollectionDemo {
	public static void main(String[] args){
		Collection coll = new ArrayList();
		show(coll);
		System.out.println("-------------------");
		Collection c1 = new ArrayList();
		Collection c2 = new ArrayList();
		show (c1, c2);
	}
	public static void show(Collection coll){
		//添加 add
		coll.add("abc1");//boolean add(Object obj);
		coll.add("abc2");
		coll.add("abc3");
		System.out.println("coll: "+coll);
		//删除 remove
		coll.remove("abc2");//boolean remove(Object obj);
		System.out.println("coll: "+coll);
		//清空 clear
		//coll.clear();
		//判断 isEmpty  contains
		System.out.println(coll.isEmpty()); //boolean isEmpty();
		System.out.println(coll.contains("abc1")); //boolean contains(Object obj);
		//获取 size
		System.out.println(coll.size()); //int size();
	}
	public static void show(Collection c1, Collection c2){
		//添加 addAll
		c1.add("abc1");
		c1.add("abc2");
		c1.add("abc3");
		c1.add("abc4");
		c2.add("abc2");
		c2.add("abc6");
		c2.add("abc7");
		System.out.println("c1: "+c1);
		System.out.println("c2: "+c2);
		c1.addAll(c2); //boolean addAll(Collection coll);
		//删除 removeAll
		boolean a = c1.removeAll(c2); //boolean removeAll(Collection coll);
		System.out.println("removeAll: "+a);
		//判断 containsAll
		boolean b = c1.containsAll(c2);
		System.out.println("containsAll: "+b); //boolean containsAll(Collection coll);
		//交集 retainAll
		boolean c = c1.retainAll(c2); //boolean retainAll(Collection coll);
		System.out.println("retain: "+c1);
	}
}
/*
 * 迭代器示例
 */
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
	public static void main(String[] args){
		Collection coll = new ArrayList();
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		coll.add("abc4");
		System.out.println(coll);
		//调用集合中的迭代器方法,获取迭代器对象
		Iterator it1 = coll.iterator();
		while(it1. hasNext()){
			System.out.println(it1.next());
		}
		//for循环结束,Iterator变量内存释放,更高效
		for(Iterator it2 = coll.iterator(); it2.hasNext();){
			System.out.println(it2.next());
		}
	}
}

二、List

Collection接口的两个子接口:
  a.List: 记录元素的保存顺序,且允许有重复元素
  b.Set: 不记录元素的保存顺序,且不允许有重复元素
  List接口: 线性表(linear list)
  List接口常用方法:
  1) 添加: add, addAll
  2) 删除: remove
  3) 修改: set
  4) 获取: get, indexOf, lastIndexOf, subList

/*
 * List集合常用方法示例
 */
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.ListIterator;
public class ListDemo {
	public static void main(String[] args){
		List list = new ArrayList();
		show(list);
	}
	public static void show(List list){
		//添加
		list.add("abc1"); //void add(index,element)
		list.add("abc3");
		list.add(1,"abc2");
		System.out.println(list);
		//删除
		System.out.println("remove: "+list.remove(2)); //Object remove(index);
		//修改
		System.out.println("set: "+list.set(1,"abc8")); //Object set(index,element);
		//获取
		System.out.println(list.get(1)); //Object get(index);
		System.out.println(list.indexOf("abc2")); //int indexOf(object);
		System.out.println(list.lastIndexOf("abc8")); //int lastIndexOf(object);
		System.out.println("sublist: "+list.subList(1, 2)); //List subList(fromIndex,toIndex);
		//迭代器
		Iterator it = list.iterator();
		for (int x = 0; x < list.size(); x++){
			System.out.println("get:"+list.get(x));
		}
	}
}

注:在迭代器过程中,不要使用集合操作元素,容易出现异常: java.util.ConcurrentModificationException。可以使用Iterator接口的子接口ListIterator来完成在迭代中对元素进行更多的操作,如下示例。

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo {
	public static void main(String[] args){
		List list = new ArrayList();
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		System.out.println("list: " + list);
		//只有List集合具有这种在迭代过程中完成对元素增删改查的特有的迭代器
		ListIterator it = list.listIterator();
		while(it.hasNext()){
			Object obj = it.next();
			if(obj.equals("abc3"))
				it.add("abc9");
		}
		System.out.println("hasNext: "+it.hasNext());
		System.out.println("hasPrevious: "+it.hasPrevious());
		while(it.hasPrevious()){
			System.out.println("previous: "+it.previous());
		}
		System.out.println("list: "+list);
	}
}

List接口的主要实现类是 ArrayList. LinkedList, 以及早期的Vector

List实现类内部数据结构同步否增删速度查询速度
ArrayList数组
LinkedList链表
Vector数组

LinkedList方法旧方法jdk1.6版本后新方法
添加addFirst(); addLast();offerFirst(); offerLast();
获取不移除getFirst(); getLast(); 如果链表为空,抛出NoSuchElementExceptionpeekFirst(); peekLast();如果链表为空,返回null。
获取并移除removeFirst(); removeLast();pollFirst(); pollLast();
方法类型可抛出异类的返回元素的
Insert(插入)add(e)offer(e)
Remove(移除)remove()poll()
Examine(检查)element()peek()

两种重要的线性数据结构
  1)栈 Stack
  遵循“后进先出”(Last In First Out, LIFO)原则
  包含三个方法
  public Object push(Object item):将指定对象压入栈中。
  Public Object pop():将 栈最上面的元素从栈中取出,并返回这个对象。
  public boolean empty():判断栈中没有对象元素。
  2)队列 Queue
  遵循“先进先出”(First In First Out,FIFO)原则
  固定在一端输入数据(称为入队),另一端输出数据(称为出队)。

/*
 * 模拟队列
 */
import java.util.LinkedList;
class Queue{
	private LinkedList link;
	public Queue(){
		link = new LinkedList();
	}
	//入队
	public void enQueue(Object obj){
		link.addLast(obj);
	}
	//出队
	public Object outQueue(){
		return link.removeFirst();
	}
	//判断队列是否为空
	public boolean isNull(){
		return link.isEmpty();
	}
}
public class QueueDemo {
	public static void main(String[] args){
		Queue d = new Queue();
		d.enQueue("abc1");
		d.enQueue("abc2");
		d.enQueue("abc3");
		d.enQueue("abc4");
		while(!d.isNull())
			System.out.println(d.outQueue());
	}
}

三、Set

Set接口中的方法和Collection一致。
  1) HashSet:内部数据结构是哈希表,是不同步的。
  2) TreeSet:可以对Set集合中的元素进行排序,是不同步的。其底层是用TreeMap来实现的
  Set中对象不重复,即:hashCode()不等。如果hashCode()相等,再看equals或==是否为false。

/*
 *ArrayList是无序列表,若要有序列表,则用LinkedHashSet 
 */
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
	public static void main(String[] args){
		HashSet hs = new LinkedHashSet();
		hs.add("abc");
		hs.add("def");
		hs.add("ghi");
		Iterator it = hs.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

TreeSet的两种排序方式:
  1)自然排序。让元素自身实现比较功能: 实现Comparable接口,覆盖compareTo方法。

/*TreeSet的两种排序方式*/
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
class Person implements Comparable{
	private String name;
	private int age;
	public Person(){
	}
	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return this.age;
	}
	public int hashCode(){
		return name.hashCode() + age * 39;
	}
	public boolean equals(Object obj){
		if (this == obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误");
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}
	public int compareTo(Object o){
		Person p = (Person) o;
		//先按照年龄排序,再按照姓名排序
		int temp = this.age-p.age;
		return temp == 0? this.name.compareTo(p.name):temp;
	}
}
public class TreeSetDemo {
	public static void main(String[] args){
		TreeSet ts = new TreeSet();
		ts.add(new Person("Amy",28));
		ts.add(new Person("Beth",23));
		ts.add(new Person("Cathy",21));
		ts.add(new Person("Caroline",23));
		ts.add(new Person("Milly",25));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Person p = (Person)it.next();
			System.out.println(p.getName()+" : "+p.getAge());
		}
	}
}

2)比较器。让集合自身具备比较功能: 定义一个类实现Comparator接口,覆盖compare方法。

import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
class Person implements Comparable{
	private String name;
	private int age;
	public Person(){
	}
	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return this.name;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return this.age;
	}
	public int hashCode(){
		return name.hashCode() + age * 39;
	}
	public boolean equals(Object obj){
		if (this == obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误");
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}
	public int compareTo(Object o){
		Person p = (Person) o;
		int temp = this.age-p.age;
		return temp == 0? this.name.compareTo(p.name):temp;
	}
}
class ComparatorByName implements Comparator{
	public int compare(Object o1, Object o2){
		Person p1 = (Person) o1;
		Person p2 = (Person) o2;
		int temp = p1.getName().compareTo(p2.getName());
		return temp == 0? p1.getAge()-p2.getAge():temp;
	}
}
public class TreeSetDemo {
	public static void main(String[] args){
		TreeSet ts = new TreeSet(new ComparatorByName());
		ts.add(new Person("Amy",28));
		ts.add(new Person("Beth",23));
		ts.add(new Person("Cathy",21));
		ts.add(new Person("Caroline",23));
		ts.add(new Person("Milly",25));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Person p = (Person)it.next();
			System.out.println(p.getName()+" : "+p.getAge());
		}
	}
}

四、Map

Map接口,即映射,是键-值对(key-value pair)的集合,map集合中必须保证键的唯一性。
  Map的层次结构如下图所示:
  

Map接口常用方法:
  1) 添加
  value put(key,value):返回前一个和key关联的值,如果没有返回null。
  2) 删除
  void clear():清空map集合。
  value remove(Object key):根据指定的key删除这个键值对。
  3)判断
  boolean containsKey(key);
  boolean containsValue(value);
  boolean isEmpty();
  4)获取
  value get(key):通过键获取值,如果没有该键返回null。
  int size():获取键值对个数。

import java.util.Map;
import java.util.HashMap;
public class MapMethodDemo {
	public static void main(String[] args){
		Map<Integer, String>map = new HashMap<Integer, String>();
		method(map);
	}
	public static void method(Map<Integer, String> map){
		//添加
		System.out.println(map.put(23,"Lucy")); //null
		System.out.println(map.put(21,"Glen")); //null
		System.out.println(map); 
		map.put(28,"Richa");
		map.put(25,"Samantha");
		System.out.println(map);
		//删除
		//map.clear();
		System.out.println("remove: "+map.remove(21));
		//判断
		System.out.println("containsKey: "+map.containsKey(23));
		System.out.println("containsValue: "+map.containsKey("Richa"));
		System.out.println("isEmpty: "+map.isEmpty());
		//获取
		System.out.println("get: "+map.get(23));
		System.out.println("size: "+map.size());
	}
}

获取Map集合元素并打印的三种方式:
  1)通过keySet方法获取map中所有的键所在的set集合,再通过set的迭代器获取到每一个键。再对每一个键通过map集合的get方法获取其对应的值。

import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
public class MapDemo {
	public static void main(String[] args){
		Map<Integer, String> map = new HashMap<Integer, String>();
		method(map);
	}
	public static void method(Map<Integer, String>map){
		map.put(23,"Lucy");
		map.put(21,"Glen");
		map.put(28,"Richa");
		map.put(25,"Samantha");
		Set<Integer> keySet = map.keySet();
		Iterator<Integer> it = keySet.iterator();
		while(it.hasNext()){
			Integer key = it.next();
			String value = map.get(key);
			System.out.println(key+" : "+value);
		}
	}
}

2)Map转成Set——entrySet方法:该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型。

import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
public class MapDemo2 {
	public static void main(String[] args){
		Map<Integer, String> map = new HashMap<Integer, String>();
		method(map);
	}
	public static void method(Map<Integer, String>map){
		map.put(23,"Lucy");
		map.put(21,"Glen");
		map.put(28,"Richa");
		map.put(25,"Samantha");
		Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
		Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+" : "+value);
		}
	}
}

3)只取value值时:将Map的value存入Collection集合,再通过Collection的迭代器获取value。

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
public class MapDemo3 {
	public static void main(String[] args){
		Map<Integer, String> map = new HashMap<Integer, String>();
		method(map);
	}
	public static void method(Map<Integer, String>map){
		map.put(23,"Lucy");
		map.put(21,"Glen");
		map.put(28,"Richa");
		map.put(25,"Samantha");
		Collection<String> values = map.values();
		Iterator<String> it = values.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
Map子类内部结构线程Remark
Hashtable哈希表同步不允许null作为键,null作为值
HashMap哈希表同步允许null作为键,null作为值
TreeMap二叉树不同步可以对Map集合中的键进行排序
/*用LinkedHashMap输出Map内容跟存入顺序一致。*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
	public static void main(String[] args){
		HashMap<Integer, String> hm = new LinkedHashMap<Integer, String>();
		hm.put(7, "Vance");
		hm.put(3, "Emily");
		hm.put(1, "Bill");
		hm.put(5, "Alex");
		Iterator<Map.Entry<Integer, String>> it = hm.entrySet().iterator();
		while(it.hasNext()){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key + ": " +value);
		}
	}
}
/*
 * 实例:输入1——7的数字,显示是星期几,并打印其英文表示
 * 分析:星期几和英文是映射关系——优先考虑HashMap
 */
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
	public static void main(String[] args){
		String week = getWeek(1);
		System.out.println(week);
		System.out.println(getWeekByMap(week));
	}
	public static String getWeekByMap(String week){
		Map<String, String> map = new HashMap<String, String>();
		map.put("星期一","Mon");
		map.put("星期二","Tue");
		map.put("星期三","Wed");
		map.put("星期四","Thu");
		map.put("星期五","Fri");
		map.put("星期六","Sat");
		map.put("星期日","Sun");
		return map.get(week);
	}
	public static String getWeek(int week){
		if (week<1 || week>7)
			throw new RuntimeException("没有对应的星期,请重新输入");
		String[] weeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
		return weeks[week];
	}
}
/*
 * 实例:获取字符串中每一个字母出现的次数。
 * 分析:映射关系——数组和Map;关系中没有顺序编号——Map;
 * 键有顺序——TreeMap
 */
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class MapTest {
	public static void main(String[] args){
		String str = "fdqavcbsacdfss";
		String s = getCharCount(str);
		System.out.println(s);
	}
	public static String getCharCount(String str){
		//将字符串变为字符数组
		char[] chs = str.toCharArray();
		//定义Map集合
		Map<Character, Integer> map = new TreeMap<Character, Integer>();
		for(int i = 0; i < chs.length; i++){
			//如果不是字母,则不统计,跳出本次循环
			if(!(chs[i]>='a' && chs[i]<='z' || chs[i] >='A' && chs[i] <='Z'))
				continue;
			//将数组中的字母作为键去查map表。返回值:map.contains(key)? null : key.equals(k))
			Integer value = map.get(chs[i]);
			int count = 0;
			//如果map中已经存在,则count = key.equals(k);
			if(value!=null){
				count = value;
			}
			count++;
			map.put(chs[i], count);
		}
		return mapToString(map);
	}
	private static String mapToString(Map<Character, Integer> map){
		StringBuilder sb = new StringBuilder();
		//定义迭代器对象迭代map中存储的键
		Iterator<Character> it = map.keySet().iterator();
		while(it.hasNext()){
			Character key = it.next();
			Integer value = map.get(key);
			sb.append(key+"("+value+")");
		}
		return sb.toString();
	}
}

四、Collections工具类

Collections:是集合框架的工具类,里面的方法都是静态的。
  Collections常用方法:
  1) 排序:sort, shuffle
  2) 查找:binarySearch, max
  3)替换:replace, replaceAll, fill, swap
  4)反转:reverse, reverseOrder
  5)同步:synchronizedList

import java.util.Collections;
import java.util.List;
import java.util.Comparator;
import java.util.ArrayList;
public class CollectionsDemo {
	public static void main(String[] args){
		demo();
	}
	public static void demo(){
		List<String> list = new ArrayList<String>();
		list.add("Caroline");
		list.add("Amy");
		list.add("Lisa");
		list.add("Sandy");
		list.add("Beth");
		list.add("Daisy");
		//对list集合进行指定顺序的排序
		Collections.sort(list);
		System.out.println(list);
		Collections.sort(list, new ComparatorByLength());
		System.out.println(list);
		mySort(list, new ComparatorByLength());
		System.out.println(list);
		//shuffle: 使用默认随机源对指定列表进行置换
		Collections.shuffle(list);
		System.out.println(list);
		//查找,找不到返回-1
		int index = Collections.binarySearch(list, "Beth");
		System.out.println("index  = "+index);
		//获取最大值
		String max = Collections.max(list, new ComparatorByLength());
		System.out.println("max = "+max);
		//替换
		Collections.replace(list,"Lisa","Milly");
		System.out.println(list);
	}
	public static <T> void mySort(List<T> list, Comparator<? super T> comp){
		for(int i = 0; i < list.size()-1; i++){
			for (int j = i+1; j < list.size(); j++){
				if(comp.compare(list.get(i), list.get(j))>0){
					Collections.swap(list, i, j);
				}
			}
		}
	}
}
class ComparatorByLength implements Comparator<String>{
	public int compare(String o1, String o2){
		int temp = o1.length()-o2.length();
		return temp == 0? o1.compareTo(o2):temp;
	}
}

五、Arrays工具类

Arrays:集合框架的工具类,里面的方法都是静态的。
  List asList(数组) 可以将数组转成集合,以便于增删操作。
  使用Collection的 toArray 方法可以将集合转成数组。当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新的数组。所以一般数组长度指定为集合的size。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArraysDemo {
	public static void main(String[] args){
		//数组——>集合: List asList(array)
		String[] arr = {"Amy", "Lucy", "Cathy"};
		List<String> list = Arrays.asList(arr);
		System.out.println(list.contains("Lucy"));
		
		int[] arr1 = {31, 11, 51, 61};
		List<int[]> list1 = Arrays.asList(arr1);
		System.out.println(list1);
		Integer[] arr2 = {31, 11, 51, 61};
		List list2 = Arrays.asList(arr2);
		System.out.println(list2);
		//集合——>数组: toArray
		List<String> list3 = new ArrayList<String>();
		list3.add("abc1");
		list3.add("abc2");
		list3.add("abc3");
		String[] arr3 = list3.toArray(new String[2]);
		System.out.println(Arrays.toString(arr3));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值