二十四、Java集合框架(二)

Collection接口

    集合是一种用来存储数据的容器,不需要考虑容量问题,会自动扩容  

    Collection接口是构造集合框架的基础,是单值数据操作的最大父接口,所谓单值数据操作的意思即,每个元素都是单一的值,类似于数组的感觉。Collection接口包含了两个子接口List和Set,Collection接口定义的很多方法,List和Set接口都继承了下来。在开发的过程中也很少直接使用Collection接口,而是更多的去使用List和Set这两个子接口


1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。

2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>

3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector>

List子类型:ArrayList(不安全高效,查询快,增删慢),LinkedList(增删快,查询慢),Vector(安全低效)


List接口的使用

代码演示:

package demo;

import java.util.ArrayList;
import java.util.List;

public class CollectionDemo {
	public static void main(String[] args) {
                //创建一个ArrayList对象
		List list = new ArrayList();
		/*
		 * 往集合存放放数据(元素)
		 * add(Object e)可以存放任何引用类型
		 */
		list.add("one");
              //一般会使用new Integer(5),这里自动包装
              list.add(1);
//集合也重写了toString()方法,在输出时,会调用元素的toString()方法System.out.println(list);}}

代码结果:

[one, 1]

代码讲解:上述代码声明父类接口List,用子类型ArrayLsit去实例化,然后调用add()方法,向列表里面添加元素,因为集合也重写了toString()方法,所以直接输出对象即可。


上述例子我们可以看到,我们存放了一个字符串,和一个整数,而我们模拟想做的是一个数组,显然不同的数据类型在集合没加泛型的情况下,都能存放进集合类,我们看add(Object obj)方法,可以看到参数上,只要是类即可,第一点:即只要是类即可插入,因为所有类的顶层都是Object类。第二点:泛型机制不支持基本数据类型,即类型参数不包含基本数据类型,我们来演示一下泛型的使用

代码演示:

package demo;

import java.util.ArrayList;
import java.util.List;

public class CollectionDemo2 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(2);
		list.add(3);
		list.add(new Integer(5));
		/*
		 * list.add("1");会出现错误,因为泛型的限制,错误信息如下
		 * The method add(Integer) in the type List<Integer> is not applicable for the arguments (String)
		 * list.add("1");
		 */
		System.out.println(list);
		
	}
}
代码结果:
[2, 3, 5]

代码讲解:可以看到上述代码,泛型机制的引用也是十分简单的只需要List<T> list = new ArrayList<T>();即可

T可以换成其他类型,但不支持基本数据类型。


我们提到过,List可以实现动态数组,即大小不用一开始就确定好。我们来检验一下

代码演示:

package lesson1015_2;

import java.util.ArrayList;
import java.util.List;

public class CollectionDemo2 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(2);
		list.add(5);
		list.add(8);
		list.add(9);
		//调用size()方法,查看List集合的长度
		System.out.println(list.size());
		//接着添加数据,观察List集合的长度变化
		list.add(3);
		System.out.println(list.size());
	}
}

代码结果:

4
5

代码讲解:通过上述例子,我们可以看到List集合不但可以通过泛型模拟数组,而且是动态增长的,即当需要添加一个元素,它会直接分配一个位置,并且存入元素的值。在内存上说,List集合相对数组来说还是比较友好的

接下来我们将统一的给大家演示一下ArrayList的其他方法

代码演示:

package demo;

import java.util.ArrayList;
import java.util.List;

public class CollectionDemo2 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(new Integer(5));
		list.add(new Integer(8));
		list.add(new Integer(9));
		list.add(new Integer(0));
		list.add(new Integer(5));
		list.add(new Integer(1));
		list.add(new Integer(4));
		//使用add(int index,Object obj)向指定位置插入元素,当前位置,和当前位置后元素响应后移一位,index从0开始
		list.add(2, new Integer(6));			
		System.out.println(list);				//[5, 8, 6, 9, 0, 5, 1, 4]
		//使用remove(Object obj)移除一个元素
		list.remove(new Integer(5));
		System.out.println(list);				//[8, 6, 9, 0, 5, 1, 4]
		//使用remove(int index)移除指定位置的元素
		list.remove(3);
		System.out.println(list);  				//[8, 6, 9, 5, 1, 4]
		/*
		 * 集合中也提供类似字符串的方法
		 * indexOf(Object obj):返回元素第一次出现的位置
		 * LastIndexOf(Object obj):返回元素最后一次出现的位置
		 */
		int index = list.indexOf(new Integer(6));
		int lastindex = list.lastIndexOf(new Integer(6));
		System.out.println("6第一次的位置:"+index);			//6第一次的位置:1
		System.out.println("6最后一次出现的位置:"+lastindex);	//6最后一次出现的位置:1
		/*
		 * toArray()将集合转换成的数组类型
		 */
		Object[] obj = list.toArray();
		int sum = 0;
		for (int i = 0; i < obj.length; i++) {
			sum = sum + ((Integer)obj[i]).intValue();
		}
		System.out.println("所有元素的和为"+sum);				//所有元素的和为33
		

		//使用clear()方法清空List集合
		list.clear();
		System.out.println(list.size());		//0
	}
}


LinkedList除了上述ArrayList使用的方法还有自己的方法

代码演示

package demo;

import java.util.LinkedList;

public class LinkedListDemo {
	public static void main(String[] args) {
		LinkedList<String> l = new LinkedList<String>();
		l.add("A");
		l.add("B");
		l.add("C");
		l.add("D");
		l.add("E");
		l.addFirst("A0");
		l.addLast("F");
		l.add(2, "A1");
		System.out.println("链表里的内容是:"+l);
		l.remove(l.size()-1);			//等价于		l.removeLast();	
		System.out.println("链表里的内容是:"+l);
		l.remove(0);					//等价于		l.removeFirst();
		System.out.println("链表里的内容是:"+l);
		l.remove(1);
		System.out.println("链表里的内容是:"+l);
		Object val = l.get(0);
		l.set(0, (String)val+"Changed");
		System.out.println("链表里的内容是:"+l);
	}
}



迭代器Iterator

    集合框架中还提供了Iterator接口,专门用于集合的迭代输出,所谓的迭代,可以理解为循环的意思

代码演示:

package demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CollectionDemo4 {
	public static void main(String[] args) {
		/*
		 * Iterator:迭代器,是一个接口
		 * List集合中提供了获取iterator的实现类的方法
		 * 用于迭代(遍历)元素
		 */
		List<String> list = new ArrayList<String>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		
		//用多态的形式
		Iterator it = list.iterator();
		/*
		 * 迭代器的特点:先问再取
		 * it.hasNext():判断是否有下一个元素
		 * it.next():取出元素
		 */
		//while循环是专门为迭代器设计的
		//注意问一次取一次,避免出现异常
		while(it.hasNext()){
			Object obj = it.next();
			if(obj.equals("b")){
				it.remove();
			}		
		}
		System.out.println(list);	
	}
}

代码讲解:上述代码演示了Iterator的使用,迭代器的使用可以使用集合对象.iterator()方法取得Iterator it对象

使用while循环遍历,需要先it.hasNext()判断迭代器是否有内容,如果有则使用it.next()移动遍历内容。

当然迭代也可以加入泛型,我们来演示一下泛型类的使用,和泛型类的迭代

代码演示:

package demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

class Point<E,K>{
	private E x;
	private K y;

	public Point() {

	}
	public Point(E x, K y) {
		super();
		this.x = x;
		this.y = y;
	}

	public E getX() {
		return x;
	}

	public K getY() {
		return y;
	}

	public void setX(E x) {
		this.x = x;
	}

	public void setY(K y) {
		this.y = y;
	}
	
	
	public String toString(){
		return "("+x+","+y+")";
	}
}
public class TestPoint {	
	public static void main(String[] args) {
		Point<Integer, Integer> p1 = new Point<Integer, Integer>(2, 2);
		Point<Integer, Integer> p2 = new Point<Integer, Integer>(3, 4);
		Point<Integer, Integer> p3 = new Point<Integer, Integer>(5, 2);
		
		List<Point<Integer, Integer>> list = new ArrayList<Point<Integer, Integer>>();
		
		list.add(p1);
		list.add(p2);
		list.add(p3);
		
		Iterator<Point<Integer, Integer>> it = list.iterator();
		while(it.hasNext()){
			Point<Integer, Integer> p = (Point<Integer, Integer>)it.next();
			System.out.println("点x坐标为"+p.getX()+",y坐标为"+p.getY());
		}
	}
}


foreach循环

   for-each循环是一种高级的for循环,for-each循环可以遍历数组也可以遍历集合

代码演示:

package demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ForecahDemo {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("one");
		list.add("two");
		list.add("three");
		//使用toArray()将集合转换成数组
		Object[] arr = list.toArray();
		System.out.println(Arrays.toString(arr));
		for (Object obj : arr) {
			System.out.println((String)obj);
		}
		
		/*
		 * 将数组转换成集合
		 * Arrays工具类中提供了一个方法
		 * asList()
		 * 转换后的集合不能增加和删除
		 * 要想接着操作,通过addAll操作,放进新的集合里
		 */
		
		String[] arr3 = new String[]{"a","b","c"};
                //将数组转换成集合对象
                List<String> list3 = Arrays.asList(arr3);
		for (Object object : list3) {
			System.out.println(object+" ");
		}
	}
}

使用for-each循环:

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

                    执行语句;

    }

for-each循环不需要写出结束条件,或者i的步长,for-each会自动遍历到数组尾或集合尾结束,即i<=a.length



比较器

      有时候需要为多个对象排序时,必须设置排序规则,而排序规则就可以通过比较器进行设置,而在java之中比较器提供有两种:Comparable和Comparator;

Comparable:适合永久的比较规则,即实体类实现接口Comparable并重写compareTo方法

Comparator:适合突然需要的比较规则,不想去修改原来实体类,而定义的一种排序规则


Comparable代码演示:

1.创建实体类Point,并实现Comparable接口

package demo;

public class Point implements Comparable<Point> {
	private int x;
	private int y;
	
	public Point(){
		
	}

	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public void setX(int x) {
		this.x = x;
	}
	public void setY(int y) {
		this.y = y;
	}


	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}

        //重写compareTo方法,定义排序规则
	public int compareTo(Point o) {
		if((this.x*this.x+this.y*this.y)>(o.x*o.x+o.y+o.y)){
			return 1;
		}else if((this.x*this.x+this.y*this.y)==(o.x*o.x+o.y+o.y)){
			return 0;
		}else {
			return -1;
		}
	}
}

2.编写测试类ComparablePointDemo,测试

package demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author 超级皮皮虾
 * @description	永久比较用Comparable 临时用Comparator
 * 
 */
public class ComparablePointDemo {
	public static void main(String[] args) {
		List<Point> p = new ArrayList<Point>();
		p.add(new Point(1, 2));
		p.add(new Point(1, 1));
		p.add(new Point(2, 2));
		System.out.println("没有排序前"+p);
		/*
		 * 如果放进集合的元素想要排序,必须实现Comparable接口
		 * 实现里面的int CompareTo(Object obj)方法
		 * 当前元素与传进来的元素进行比较
		 * 当前元素大于传进来的元素,则返回>0
		 * 当前元素等于传进来的元素,则返回=0
		 * 当前元素小于传进来的元素,则返回<0
		 */
                //使用Collections算法的sort(List list)方法进行排序
                Collections.sort(p);
		System.out.println("使用排序后"+p);
	}
}




代码结果:

没有排序前[Point [x=1, y=2], Point [x=1, y=1], Point [x=2, y=2]]
使用排序后[Point [x=1, y=1], Point [x=1, y=2], Point [x=2, y=2]]

Comparator代码演示:

1.创建实体类Point,并实现Comparable接口

package demo;

public class Point implements Comparable<Point> {
	private int x;
	private int y;
	
	public Point(){
		
	}

	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public void setX(int x) {
		this.x = x;
	}
	public void setY(int y) {
		this.y = y;
	}


	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}

        //重写compareTo方法,定义排序规则
	public int compareTo(Point o) {
		if((this.x*this.x+this.y*this.y)>(o.x*o.x+o.y+o.y)){
			return 1;
		}else if((this.x*this.x+this.y*this.y)==(o.x*o.x+o.y+o.y)){
			return 0;
		}else {
			return -1;
		}
	}
}
2.编写测试类ComparablePointDemo2,测试
package demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparablePointDemo {
	public static void main(String[] args) {
		List<Point> p = new ArrayList<Point>();
		p.add(new Point(1, 2));
		p.add(new Point(1, 1));
		p.add(new Point(2, 2));
		System.out.println(p);
		
				
		/*	原来的Point不能变的情况,想临时改变排序规则
		   	我们可以调用sort的重载方法
		 	sort(Collection c,Comparator c):
			Comparator是比较器接口,需要重写接口里的compare(Object obj1,Object obj2)
		 	obj1> obj2 返回>0 
		 	obj1= obj2 返回=0 
		 	obj1< obj2 返回<0 */
		
		//使用匿名内部类创建
		Comparator<Point> my = new Comparator<Point>() {

			@Override
			public int compare(Point o1, Point o2) {
				return -(o1.getX()-o2.getX());
			}
			
		};
		
		Collections.sort(p, my);
		System.out.println(p);
	}
}


代码结果:

[Point [x=1, y=2], Point [x=1, y=1], Point [x=2, y=2]]
[Point [x=2, y=2], Point [x=1, y=2], Point [x=1, y=1]]

代码讲解:我们可以看到Point类原本实现了Comparable接口,并且完成comparaTo方法的重写,这时候向临时改变排序规则,就可以不需要修改Point类,使用匿名内部类的方法创建Comparator类的对象,并且实现compare方法,使用Collections.sort(List list,Comparator mycom)来进行排序




    

猜你喜欢

转载自blog.csdn.net/qq_38741971/article/details/80257204