java集合概述

Java集合概述

由于Java是纯面向对象编程的,为了可以更方便的对多个对象进行操作,就要对对象进行存储,因此我们通常会用到集合来存储多个对象。

1.   为啥很少用数组?

有Java基础的都知道,数组在使用之前必须要创建,并且在数组创建之后其长度是不可以改变的;但是集合就不一样了,因为集合的长度是可以改变的;还有,集合中只能存储对象而不能存储基本数据类型(int,long,float,double等)。正是由于数组诸多的局限性,所以在很多时候我们用到的是Java的集合框架,而不是数组。

2.   集合分类

集合类图如下:(分类是根据每一个容器对数据的存储方式的不同来划分的)


3.   常用的共性方法:包括

boolean java.util.Collection.add(T) 添加元素

boolean java.util.Collection.isEmpty() 判断是否为空

boolean java.util.Collection.remove(Object o) 移除某个元素

void java.util.Collection.clear() 清空集合

Object[] java.util.Collection.toArray() 将集合转换数组

下面我们来看一个例子:

package learn.collections;

import java.util.ArrayList;
import java.util.Collection;

/*集合测试Demo*/
public class CollectionsTest {

	public static void main(String[] args) {
		Collection<String> collection = new ArrayList<String>();
		/* 循环向集合中添加元素 */
		for (int i = 0; i < 10; i++) {
			collection.add("元素" + i);
		}
		/* 打印集合中的元素 */
		System.out.println(collection);
		/* 移除元素1 */
		collection.remove("元素1");
		/* 打印移除元素1后的集合 */
		System.out.println(collection);
		/* 清空集合 */
		collection.clear();
		/* 打印集合大小 */
		System.out.println("集合的大小:"+collection.size());
		/* 打印集合是否为空 */
		System.out.println("集合是否为空:"+collection.isEmpty());
		/* 打印集合是否包含元素1 */
		System.out.println("集合是否包含元素1:"+collection.contains("元素1"));
		collection.add("元素1");
		System.out.println("集合是否包含元素1:"+collection.contains("元素1"));
	}
}
运行结果:

</pre><pre name="code" class="java">输出结果为:
[元素0, 元素1, 元素2, 元素3, 元素4, 元素5, 元素6, 元素7, 元素8, 元素9]
[元素0, 元素2, 元素3, 元素4, 元素5, 元素6, 元素7, 元素8, 元素9]
集合的大小:0
集合是否为空:true
集合是否包含元素1:false
集合是否包含元素1:true

由以上代码可知:

1.add方法的参数类型为Object

2.集合中存储的都是对象的引用

然后再来看一下一组元素(集合)的方法:

package learn.collections;
	public static void demo2(){
		Collection col1=new ArrayList();
		col1.add("java01");
		col1.add("java02");
		
		Collection col2=new ArrayList();
		col2.add("java01");
		col2.add("java03");
		
		String demoMethod="containsAll";
		switch (demoMethod) {
		case "addAll":
			//求并集,重复不合并
			col1.addAll(col2);//[java01, java02, java01, java03]
			System.out.println(col1);
			break;
		case "removeAll":
			col1.removeAll(col2);//[java02]求差集
			System.out.println(col1);
			break;
		case "retainAll":
			col1.retainAll(col2);//[java01]求交集
			System.out.println(col1);
			break;
		case "containsAll":
			col1.add("java03");
			System.out.println(col1.containsAll(col2));//true
		default:
			break;
		}		
	}


学习本节后的结合框架如图:

本节学了1个接口,10个方法的用法

迭代器

迭代器是逐个取出集合元素的方式,迭代器接口在各个集合类中实现都不一样。每个集合类的iterator()方法返回的迭代器对象也不一样,是每个集合内部定义的类。

使用迭代器获取元素的代码如下:

package learn.collections;

	public static void demo3(){
		Collection col1=new ArrayList();
		for (int i = 0; i < 10000; i++) {
			col1.add("测试数据"+i);
		}
		long startTime=System.currentTimeMillis();
		//用迭代器取出元素方式1,传统方式
//		Iterator it=col1.iterator();
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
		//用迭代器取出元素方式2,将迭代器在for循环的第一个;前定义,可以提高性能
		for (Iterator it=col1.iterator();it.hasNext();) {
			System.out.println(it.next());
		}
		System.out.println(System.currentTimeMillis()-startTime);
	}

学习本节后,集合框架体系图为:

本节学习了1个接口,3个方法,本章到这学习了2个接口,13个方法

List集合共性方法

List接口和Set接口对比:

List:元素是有序的,元素可以重复。该集合体系有索引

Set:元素是无序的,元素不可以重复。

List集合特有方法。凡是可以操作角标的方法都是该体系特有的方法。元素索引从0开始。

add(index,element);加到index指向的元素前边

addAll(index,Collection);

remove(index);

set(index,element);

get(index);

indexOf();

subList(from,to);

listIterator();

再来看一个例子:

package learn.collections;
public static void demo1(){
		List list1=new ArrayList();
		list1.add("java01");
		list1.add("java02");
		list1.add("java03");
		
		List list2=new ArrayList();
		list2.add("java04");
		list2.add("java05");
		
		String method="indexOf(element)";
		switch (method) {
		case "add(index,element)":
			list1.add(0,"java04");
			System.out.println(list1);
			list1.add(1,"java05");
			System.out.println(list1);
			break;
		case "addAll(index,Collection)":
			list1.addAll(2,list2);
			System.out.println(list1);
			break;
		case "remove(index)":
			list1.remove(1);
			System.out.println(list1);
			list1.remove(1);
			System.out.println(list1);
			break;
		case "set(index,element)":
			list1.set(1, "java11");
			System.out.println(list1);
			break;
		case "get(index)":
			//获取一个元素
			System.out.println(list1.get(0));
			//获取所有元素
			for (int i = 0,max=list1.size(); i < max; i++) {
				System.out.println(list1.get(i));
			}
			break;
		case "subList(from,to)":
			List list3=list1.subList(1, 3);
			System.out.println(list3);
			break;
		case "indexOf(element)":
			int index=list1.indexOf("java01");
			System.out.println(index);
			break;
		default:
			break;
		}
	}


学习本节后集合框架体系图为:


本节学习了1个接口,7个方法,本章到这学习了3个接口,20个方法

ListIterator

ListIterator是List集合特有的迭代器。ListIterator是Iterator的子接口。Iterator的局限性:Iterator迭代时不能通过集合对象的方法操作集合中的元素,否则会发生ConcurrentModificationException异常。所以在迭代时,只能用迭代器的方法操作元素,可是Iterator中只有判断,取出和删除的操作。如果想要进行其他操作如添加,修改等,就需要使用其他子接口,既ListIterator。该接口只能通过List集合的listIterator()方法获取。

下面的代码演示Iterator的局限性和remove方法

package learn.collections;
	public static void demo2(){
		List list1=new ArrayList();
		list1.add("java01");
		list1.add("java02");
		list1.add("java03");
		
		Iterator it=list1.iterator();
		while(it.hasNext()){
			Object obj= it.next();
			if (obj.equals("java02")) {
//				list1.add("java04");//不能添加元素,会报异常
				it.remove();//Iterator的方法,从集合中删除java02的引用	
				System.out.println(obj);//删除的是引用而不是对象,所以能取到
			}		
		}
		System.out.println(list1);	
	}
下面的代码演示ListIterator的用法

package learn.collections;
public static void demo3(){
		List list1=new ArrayList();
		list1.add("java01");
		list1.add("java02");
		list1.add("java03");
		System.out.println(list1);
		ListIterator it=list1.listIterator();
		while(it.hasNext()){
			Object obj= it.next();
			if (obj.equals("java02")) {
				//可以用list迭代器自己的add和set方法,
				//但不能同时使用,否则报异常
//				it.add("java05");
				it.set("java04");
			}		
		}
		System.out.println(list1);	
	}
下面的代码演示ListIterator正向遍历和逆向遍历

package learn.collections;	
public static void demo4(){
		List list1=new ArrayList();
		list1.add("java01");
		list1.add("java02");
		list1.add("java03");
				
		ListIterator it=list1.listIterator();

		while(it.hasNext()){
			System.out.println(it.nextIndex());
			System.out.println(it.next());		
		}
		
		while(it.hasPrevious()){
			System.out.println(it.previousIndex());
			System.out.println(it.previous());		
		}
	}

注意,直接逆向遍历是没有结果的,it.previousIndex()初始会返回-1。需要先用正向遍历把指针调到最后一个位置,才能开始逆向遍历,所以逆向遍历很少用,一般用previous()方法配合next()方法使用。

学习本节后集合框架体系图为:


本节学习了1个接口,7个方法,本章到这学习了4个接口,27个方法

List集合具体对象特点

ArrayList:底层使用数组。特点:查询速度很快,增删稍慢,线程不同步。

LinkedList:底层使用链表。特点:增删很快,查询稍慢。

Vector:底层使用数组。线程同步。历史较长。现被ArrayList替代。

Vector中有一系列方法带element,这是它特有的方法,这些方法和Collection集合中的方法重复,且元素名过长,所以被取代,还有一个elements()方法返回Enumeration对象,Enumeration接口和Iterator接口功能雷同,但是方法名过长,所以被Iterator取代。

Vector中的部分方法演示如下:

package learn.collections;
	public static void demo5(){
		Vector v=new Vector();
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
		
		Enumeration en=v.elements();
		while (en.hasMoreElements()) {
			System.out.println(en.nextElement());		
		}
	}

LinkedList

LInkedList特有方法:

添加元素

addFirst()

addLast()

获取元素(会删除元素。如果集合中没有元素,会出现NoSuchElementException)

getFirst()

getLast()

获取元素(元素会被删除。如果集合中没有元素,会出现NoSuchElementException)

removeFirst()

removeLast()

JDK1.6后出现了替代方法

添加元素

offerFirst()

offerLast()

获取元素(会删除元素。如果集合中没有元素,会返回null)

peekFirst()

peekLast()

获取元素(元素会被删除。如果集合中没有元素,会返回null)

pollFirst()

pollLast()

演示代码如下:

package learn.collections;
	public static void demo1(){
		LinkedList  link=new LinkedList();
		link.addFirst("java01");
		link.addFirst("java02");
		link.addFirst("java03");
		link.addFirst("java04");
		System.out.println(link);
		String method="pollLast";
		switch (method) {
		case "addLast":
			link.addLast("java05");
			link.addLast("java06");
			System.out.println(link);
			break;
		case "getFirst":
			System.out.println(link.getFirst());
			System.out.println(link);
			break;
		case "getLast":
			System.out.println(link.getLast());
			System.out.println(link);
			break;
		case "removeFirst":
			System.out.println(link.removeFirst());
			System.out.println(link);
			break;
		case "removeLast":
			System.out.println(link.removeLast());
			System.out.println(link);
			break;
		case "offerfirst":
			link.offerFirst("java05");
			link.offerFirst("java06");
			System.out.println(link);
			break;
		case "offerLast":
			link.offerLast("java05");
			link.offerLast("java06");
			System.out.println(link);
			break;
		case "peekFirst":
			System.out.println(link.peekFirst());
			System.out.println(link);
			break;
		case "peekLast":
			System.out.println(link.peekLast());
			System.out.println(link);
			break;
		case "pollFirst":
			System.out.println(link.pollFirst());
			System.out.println(link);
			break;
		case "pollLast":
			System.out.println(link.pollLast());
			System.out.println(link);
			break;
		default:
			break;
		}
	}

 

下面用LinkedList模拟一个堆栈或队列

堆栈:先进后出 First In Last Out FILO,如同一个杯子

队列:先进先出 First In First Out FIFO,好比排队

package learn.collections;
import java.util.LinkedList;

class Queue{
	private LinkedList link;
	public Queue(){
		link=new LinkedList();
	}
	public void push(Object obj){
		link.offerFirst(obj);
	}
	public Object pop(){
		return link.pollLast();
	}
	public boolean isNull(){
		return link.isEmpty();
	}
}
class Stack{
	private LinkedList link;
	public Stack(){
		link=new LinkedList();
	}
	public void push(Object obj){
		link.offerFirst(obj);
	}
	public Object pop(){
		return link.pollFirst();
	}
	public boolean isNull(){
		return link.isEmpty();
	}
}


public class LinkedListDemo {
	public static void main(String[] args) {
		Queue queue=new Queue();
		queue.push("java01");
		queue.push("java02");
		queue.push("java03");
		while (!queue.isNull()) {
			System.out.println(queue.pop());		
		}
		
		Stack stack=new Stack();
		stack.push("java01");
		stack.push("java02");
		stack.push("java03");
		while (!stack.isNull()) {
			System.out.println(stack.pop());		
		}
	}
}

学习本节后集合框架体系图为:


本节学习了1个类,12个方法,本章到这学习了1个类,4个接口,39个方法.

ArrayList

一般情况下创建集合默认用ArrayList,如果增删很多用LinkedList。编写代码去除ArrayList中的重复元素

package learn.collections;
import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListDemo {
	public static void main(String[] args) {
		ArrayList list=new ArrayList();
		list.add("java01");
		list.add("java02");
		list.add("java01");
		list.add("java03");
		
		list=singleElement(list);
		System.out.println(list);
	}
	public static ArrayList singleElement(ArrayList list){
		Iterator it=list.iterator();
		
		ArrayList temp=new ArrayList();
		while (it.hasNext()) {
			Object object = (Object) it.next();
			if (!temp.contains(object)) {
				temp.add(object);
			}
		}	
		return temp;
	}
}

将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

比如:存人独享。同姓名同年龄,视为同一个人,为重复元素。

package learn.collections;
import java.util.ArrayList;
import java.util.Iterator;

class Person{
	private String name;
	private int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Person) {
			Person p=(Person)obj;
			return p.getName()==this.getName()&&p.getAge()==this.getAge();
		}
		return super.equals(obj);
	}
}


public class ArrayListDemo {
	public static void main(String[] args) {
		ArrayList list=new ArrayList();
		list.add(new Person("lisi01", 23));
		list.add(new Person("lisi02", 21));
		list.add(new Person("lisi03", 19));
		list.add(new Person("lisi02", 21));
		
		list=singleElement(list);
		list.remove(new Person("lisi01", 23));
		
		Iterator it=list.iterator();
		while (it.hasNext()) {
			Person p = (Person) it.next();
			System.out.println(p.getName()+"的年龄为"+p.getAge());
		}
	}

	public static ArrayList singleElement(ArrayList list){
		Iterator it=list.iterator();
		
		ArrayList temp=new ArrayList();
		while (it.hasNext()) {
			Object object = (Object) it.next();
			if (!temp.contains(object)) {
				temp.add(object);
			}
		}	
		return temp;
	}
}

上面的代码中实际上Person对象的equals方法是Collection对象的contains方法调用的。

本节学习了1个类(ArrayList),1个方法(equals()),截止到目前已经学习了3个类,4个接口,40个方法

HashSet

Set:元素是无序的(存入和取出的顺序不一致),元素不允许重复

|--HashSet:底层数据结构是哈希表。通过Object上的hashCode方法来判断元素是否重复,如果hashCode一样,则进一步通过equals方法判断,如果连equals都一样,则确认是重复元素

Set接口和Collection接口方法一样,所以用法没有区别。

hashCode()方法是Object类上的方法

下面的代码演示HashSet集合的元素无序性和唯一性

package learn.collections;
import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
	public static void main(String[] args) {
		HashSet set=new HashSet();
		System.out.println(set.add("java01"));
		System.out.println(set.add("java01"));
		set.add("java02");
		set.add("java03");
		set.add("java04");
		
		Iterator it=set.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());		
		}
	}
}
在HashSet中存储自定义对象,例如Person对象,并重写hashCode和equals方法:

package learn.collections;
import java.util.HashSet;
import java.util.Iterator;

class Person{
	private String name;
	private int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	@Override
	public boolean equals(Object obj) {
		System.out.println(name+".equals");
		if (obj instanceof Person) {
			Person p=(Person)obj;
			return p.getName()==this.getName()&&p.getAge()==this.getAge();
		}
		return super.equals(obj);
	}
	@Override
	public int hashCode() {
		System.out.println(name+".hashCode");
		return name.hashCode()+age*39;
	}
}

public class HashSetDemo {
	public static void main(String[] args) {
		HashSet set=new HashSet();
		set.add(new Person("lisi01", 11));
		set.add(new Person("lisi02", 21));
		set.add(new Person("lisi02", 21));
		set.add(new Person("lisi02", 26));
		set.add(new Person("lisi03", 19));
		
		Iterator it=set.iterator();
		while (it.hasNext()) {
			Person p=(Person)it.next();
			System.out.println(p.getName()+"的年龄是"+p.getAge());		
		}
	}
}

 下面演示HashCode的判断元素和删除元素方法 

package learn.collections;
public class CollectionsTest{
	public static void main(String[] args) {
		HashSet set=new HashSet();
		set.add(new Person("a1", 12));
		set.add(new Person("a2", 34));
		set.add(new Person("a3", 56));
		
		System.out.println(set.contains(new Person("a2", 34)));
		System.out.println(set.remove(new Person("a2", 34)));
		
		Iterator it=set.iterator();
		while (it.hasNext()) {
			Person p=(Person)it.next();
			System.out.println(p.getName()+"的年龄是"+p.getAge());		
		}
	}
}
上面的代码和运行结果说明,HashSet的contains方法和remove方法也是靠hashCode()方法判断元素是否相同,hashCode相同再判断equals()方法。

本节学习了1个类(HashSet)、1个方法(hashCode())。本章到目前为止共学习了4个类、4个接口、41个方法

TreeSet

Set:无序,不可以重复元素。

|-- HashSet:底层数据结构是哈希表。线程非同步的。

|-- TresSet:可以对集合中的元素排序。底层数据结构是二叉树,通过元素的compareTo方法是否返回0保证元素唯一性。

TreeSet排序第一种方式:让元素自身具备比较性。

元素需要实现Comparable接口,覆盖compareTo方法。

这种方式称为元素的自然顺序或默认顺序。

TreeSet排序第二种方式:让容器具备比较性。

创建TreeSet时传入实现Comparator接口的类,覆盖compare方法。

这种方式比较常用,且此方式比第一种方式优先级高。

下面的代码,演示一下TreeSet的顺序问题:

		TreeSet ts=new TreeSet();
		ts.add("Dac");
		ts.add("aac");
		ts.add("bac");
		ts.add("bbc");
		
		Iterator it=ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
运行结果:

Dac
aac
bac
bbc

下面的代码演示TreeSet存储对象,并排序:

import java.util.Iterator;
import java.util.TreeSet;

class Student implements Comparable{
	String name;
	int age;
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}

	@Override
	public int compareTo(Object o) {
		if (!(o instanceof Student)) {
			throw new RuntimeException();
		}
		Student s=(Student)o;
		if (this.age>s.getAge()) {
			return 1;
		}else if (this.age==s.getAge()) {
			return this.name.compareTo(s.name);
		}
		return -1;
	}
}

public class TreeSetDemo {
	public static void main(String[] args) {
		demo2();
	}
	public static void demo2(){
		TreeSet ts=new TreeSet();
		ts.add(new Student("lisi01", 56));
		ts.add(new Student("lisi02", 34));
		ts.add(new Student("lisi03", 34));
		ts.add(new Student("lisi04", 12));
		
		Iterator it=ts.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s.getName()+"的年龄是:"+s.getAge());
		}
	}
}
注意:存入TreeSet集合中的元素类必须实现Comparable接口,并覆盖compareTo方法。方法抛出异常。compareTo方法的作用是确定对象在集合中的顺序,如果compareTo方法返回1,则放在当前比较元素的后边,否则放前边。

下面的代码演示使用Comparetor来排序元素

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

class Student implements Comparable{
	String name;
	int age;
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}

	@Override
	public int compareTo(Object o) {
		if (!(o instanceof Student)) {
			throw new RuntimeException();
		}
		Student s=(Student)o;
		if (this.age>s.getAge()) {
			return 1;
		}else if (this.age==s.getAge()) {
			return this.name.compareTo(s.name);
		}
		return -1;
	}
}

class MyComparator implements Comparator
{

	@Override
	public int compare(Object o1, Object o2) {
		Student s1=(Student)o1;
		Student s2=(Student)o2;
		int ret=s1.getName().compareTo(s2.getName());
		if (ret==0) {
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return ret;
	}
}

public class TreeSetDemo {
	public static void main(String[] args) {
		demo2();
	}
	public static void demo2(){
		TreeSet ts=new TreeSet(new MyComparator());
		ts.add(new Student("lisi01", 56));
		ts.add(new Student("lisi02", 34));
		ts.add(new Student("lisi03", 34));
		ts.add(new Student("lisi04", 12));
		
		Iterator it=ts.iterator();
		while(it.hasNext()){
			Student s=(Student)it.next();
			System.out.println(s.getName()+"的年龄是:"+s.getAge());
		}
	}
}
下面的代码演示:在HashSet中存储字符串,并按字符串长度排序:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo2 {
	public static void main(String[] args) {
		TreeSet hs=new TreeSet(new Comparator() {

			@Override
			public int compare(Object o1, Object o2) {
				String s1=(String)o1;
				String s2=(String)o2;
				int ret=new Integer(s1.length()).compareTo(new Integer(s2.length()));
				if (ret==0) {
					return s1.compareTo(s2);
				}
				return ret;
			}
			
		});
		hs.add("a");
		hs.add("abd");
		hs.add("abc");
		hs.add("ab");
		hs.add("abcd");
		
		Iterator it=hs.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}	
	}
}
本节共学习了2个接口(Comparable和Comparator),2个方法(compareTo和compare),1个类TreeSet,本章到这里共学习5个类,6个接口,43个方法。

下面是到本节结束为止学习的内容的UML类图:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值