黑马程序员—Java基础—集合框架2


------- android培训java培训、期待与您交流! ----------


集合框架2

一、TreeSet
1、Set:无序,不可以重复元素
|--HashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。


|--TreeSet:可以对Set集合中的元素进行排序,验证程序如下。

import java.util.*;
class TreeSetDemo
{
	public static void main(String[] args)
	{
		TreeSet ts= new TreeSet();
		ts.add("cba");
		ts.add("aaa");
		ts.add("dbc");
		ts.add("Dac");

		Iterator it=ts.iterator();
		while (it.hasNext())
		{
			System.out.println(it.next());
		}

	}
}

二、TreeSet存储自定义对象

需求:
往TreeSet集合中存储自定义对象学生。
想按照学生的年龄进行排序。

记住,排序时,当主要条件相同时,一定判断一下次要条件。

import java.util.*;
class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));  //02首先进入内存
		ts.add(new Student("lisi007",20)); //007进入内存,调用compareTo方法,和02比较
		ts.add(new Student("lisi09",19));  //09进入内存,调用compareTo方法,和02 /07比较


		//ts.add(new Student("lisi08",19));
		//ts.add(new Student("lisi007",20));
		//ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}

class Student implements Comparable //该接口强制让学生具备比较性,符合comparable接口,自动调用compareTo方法
{
	private String name;
	private int age;

	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj)
	{

		//return 0;
		
		if(!(obj instanceof Student)) //instanceof用于判断obj是不是Student对象
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj; 

		System.out.println(this.name+"....compareto....."+s.name);
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);  //主要条件年龄相同,以次要条件——姓名作为比较方式。姓名为Sting类,已经实现了compareTo方法,可以直接调用
		}
		return -1;
		
	}

	public String getName()
	{
		return name;

	}
	public int getAge()
	{
		return age;
	}
}

三、二叉树
    底层数据结构是二叉树数据结构
二叉树数据结构特点:左小右大的数据结构,特高比较性能,又被称为红黑树,比较时先去中间数字,可以提高比较效率
保证元素唯一性的依据,通过,compareTo方法return 0.

    TreeSet排序的第一种方式:让元素(列入示例程序中的student)自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。


四、实现Comparator方式排序(常用,对外提供接口,提供功能扩展)
    TreeSet的第二种排序方式,当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性,在集合初始化时,就有了比较方式。
    当两种排序都存在时,以比较器为主。
    定义一个类,实现Comparator接口,覆盖compare方法。
class Student implements Comparable//该接口强制让学生具备比较性。
{
	private String name;
	private int age;

	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj)  //学生比较器,
	{

		//return 0;
		
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;

		//System.out.println(this.name+"....compareto....."+s.name);
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);
		}
		return -1;
		
	}

	public String getName()
	{
		return name;

	}
	public int getAge()
	{
		return age;
	}
}

class TreeSetDemo2 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet( new MyCompare());  //构造一个新的空 TreeSet,它根据指定比较器进行排序
		//TreeSet ts = new TreeSet();    以学生比较器为主的写法

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi02",21));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi007",29));
		//ts.add(new Student("lisi007",20));
		//ts.add(new Student("lisi01",40));

		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}

class MyCompare implements Comparator  //定义一个比较器
{
	public int compare(Object o1,Object o2)
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;

		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
		{

           //第一种年龄比较写法
			
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1;

			//	return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));  第二种年龄比较写法
			
		}
		return num;

	}
}

五、TreeSet练习

练习:按照字符串长度排序。

字符串本身具备比较性。但是它的比较方式不是所需要的。

这时就只能使用比较器。
import java.util.*;
class  TreeSetTest
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new StrLenComparator());

		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("aaa");
		ts.add("z");
		ts.add("hahaha");

		Iterator it = ts.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next());
		}
	}
}

class StrLenComparator implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		String s1=(String)o1;
		String s2=(String)o2;
		
		int num=new Integer(s1.length).compareTo(new Integer(s2.length()));
		if(num==0)
		return s1.compareTo(s2);

		return num;
	}	
}

另一种写法——匿名内部类
import java.util.*;
class  TreeSetTest
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new Comparator()
		{
			public int compare(Object o1,Object o2)
		    {
		         String s1=(String)o1;
		         String s2=(String)o2;
		
		         int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
		         if(num==0)
		         return s1.compareTo(s2);

		         return num;
			}
	      });

		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("aaa");
		ts.add("z");
		ts.add("hahaha");

		Iterator it = ts.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next());
		}
	}
}

六、泛型概述

1.5版本可以添加基本数据类型,
要避免,程序编译没问题,运行有问题,列入一下程序编译没问题,但是运行就会出现数据类型转换异常

泛型可以解决以上问题

泛型(可以简单理解为广泛的类型)
JDK1.4版本之前,程序员主管判断,即事先知道存储的元素为String
JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。

好处
1.将运行时期出现问题ClassCastException,转移到了编译时期。,
方便于程序员解决问题。让运行时问题减少,安全。,

2,避免了强制转换麻烦。

import java.util.*;
class GenericDemo 
{
	public static void main(String[] args) 
	{

		//ArrayList al = new ArrayList();

        //泛型表示方法,编译失败,暴露问题
        ArrayList<String> al = new ArrayList<String>();

		//<> 泛型
		//{} 程序结构
		//()参数
		//[] 数组
		al.add("abc01");
		al.add("abc0991");
		al.add("abc014");

		al.add(4);//al.add(new Integer(4));
		
        //设定it为String类型
		Iterator<String> it = al.iterator();
		while(it.hasNext())
		{
			String s = it.next();

			System.out.println(s+":"+s.length());
		}
	}
}

七、泛型使用
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,
只要见到<>就要定义泛型。
其实<> 就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

import java.util.*;
class GenericDemo2 
{
	public static void main(String[] args) 
	{
		TreeSet<String> ts = new TreeSet<String>(new LenComparator());

		ts.add("abcd");
		ts.add("cc");
		ts.add("cba");
		ts.add("aaa");
		ts.add("z");
		ts.add("hahaha");


		Iterator<String> it = ts.iterator();

		while(it.hasNext())
		{
			String s = it.next();
			System.out.println(s);
		}
	}
}


class LenComparator implements Comparator<String>//泛型
{
	public int compare(String o1,String o2)//泛型,对于equal不能用此方法
	{
		//倒序排列写法,交换o2和o1值
		int num = new Integer(o2.length()).compareTo(new Integer(o1.length()));

		if(num==0)
			return o2.compareTo(o1);
		return num;
	}
}

八、泛型类

class Tool
{
	private Worker w;
	public void setWorker(Worker w)
	{
		this.w = w;
	}
	public Worker getWorker()
	{
		return w;
	}
}

class Worker
{

}
class Student
{
}
//泛型前做法。
class Tool
{
	private Object obj;
	public void setObject(Object obj)
	{
		this.obj = obj;
	}
	public Object getObject()
	{
		return obj;
	}
}

泛型类。
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
class Utils<QQ>
{
	private QQ q;
	public void setObject(QQ q)
	{
		this.q = q;
	}
	public QQ getObject()
	{
		return q;
	}
}


class  GenericDemo3
{
	public static void main(String[] args) 
	{

		Utils<Worker> u = new Utils<Worker>();

		u.setObject(new Student());
		Worker w = u.getObject();;
		
		Tool t = new Tool();
		t.setObject(new Student());
		Worker w = (Worker)t.getObject();
		
	}
}

九、泛型方法

import java.util.*;
class Demo
{
	public <T>void show(T t)
	{
		System.out.println("show:"+t);
	}
	public <T> void print(T t)
	{
		System.out.println("show:"+t);
	}
}

class GenericDemo4 
{
	public static void main(String[] args) 
	{
	     Demo d = new Demo();
		d.show("haha");
		d.show(new Integer(4));
		d.print("heihei");		
	}
}
例如:ArrayList<E>集合,类型明确后,所有方法操作的都是同一个类型

十 、静态方法泛型

静态方法不可以访问类上定义的泛型。以下程序为错误写法
import java.util.*;
class Demo<T>
{
	public <T>void show(T t) //操作类型和对象一样
	{
		System.out.println("show:"+t);
	}
	public <Q> void print(Q t)  //操作对象与方法一致
	{
		System.out.println("show:"+t);
	}
	public  static <T> void method(T t) //与类操作类型相同,错误
	{
		System.out.println("method:"+t);
	}
}
class GenericDemo4 
{
	public static void main(String[] args) 
	{
	     Demo <String> d = new Demo<String>();
		d.show("haha");
		d.print(5);
	}
}
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
import java.util.*;
class Demo<T>
{
	public <T>void show(T t) //操作类型和对象一样
	{
		System.out.println("show:"+t);
	}
	public <Q> void print(Q t)  //操作对象与方法一致
	{
		System.out.println("show:"+t);
	}
	public  static <W> void method (W t) //与类操作类型不相同,正确
	{
		System.out.println("method:"+t);
	}
	//常见错误写法 public static void<W> method(W t)或public <W>static  void method(W t),正确写法为返回类型+函数名

}

class GenericDemo4 
{
	public static void main(String[] args) 
	{
	     Demo <String> d = new Demo<String>();
		d.show("haha");
		d.print(5);
		Demo.method("heihei");
	}
}

十一 、泛型接口
子类已经知道操作类型
interface Inter<T>
{
	void show(T t);
}

class InterImpl implements Inter<String>
{
	public void show(String t)
	{
		System.out.println("show :"+t);
	}
}

class GenericDemo5 
{
	public static void main(String[] args) 
	{

		InterImpl i = new InterImpl();
		i.show("haha");
	}
}
子类已经知道操作类型
interface Inter<T>
{
	void show(T t);
}

class InterImpl<T> implements Inter<T>
{
	public void show(T t)
	{
		System.out.println("show :"+t);
	}
}
class GenericDemo5 
{
	public static void main(String[] args) 
	{

		InterImpl<Integer> i = new InterImpl<Integer>();
		i.show(4);

	}
}

十二、泛型限定
1、对象类型不确定,使用通配符表示
import java.util.*;

class  GenericDemo6
{
	public static void main(String[] args) 
	{
		
		ArrayList<String> al = new ArrayList<String>();

		al.add("abc1");
		al.add("abc2");
		al.add("abc3");

		ArrayList<Integer> al1 = new ArrayList<Integer>();
		al1.add(4);
		al1.add(7);
		al1.add(1);

		printColl(al);
		printColl(al1);

	
    public static void printColl(ArrayList<?> al)  // ?通配符
    {  
		Iterator<?> it = al.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next().toString());
            //System.out.println(it.next().length()); 
			//错误写法,如同多态,不能预先使用子类中特有方法,通配符不能保证可以使用length,列入通配符为Integer中就没有length,
			//但是toString可以使用,因为任何类型都具备toString
		}
	}
    //另外一种表示方式
	  public static <T> void printColl(ArrayList<T> al)  // T通配符
      {  
		  Iterator<T> it = al.iterator();

		  while(it.hasNext())
		  {
			  T t =it.next();
			  System.out.println(t);
		  }
	  }
}
2、类型不匹配,会导致错误
import java.util.*;
class Person
{
	private String name;
	Person(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
}

class Student extends Person
{
	Student(String name)
	{
		super(name);
	}

}

class GenericDemo4 
{
	public static void main(String[] args) 
	{
	   ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("abc1"));
		al.add(new Person("abc2"));
		al.add(new Person("abc3"));
        //printColl(al);

		ArrayList<Person> al = new ArrayList<Person>();
		all.add(new Student("abc--1"));
		all.add(new Student("abc--2"));
		all.add(new Student("abc--3"));
        printColl(all); 
		//ArrayList<Student> al=new ArrayList<Person>();error,类型不匹配
	}
	public static void printColl(ArrayList <Person> al)
	{
		Iterator< Person> it = al.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}

3.使用泛型限定写法

 上限限定,列入TreeSet中的Comparator
public static void printColl(ArrayList <? extends Person> al)
	{
		Iterator<? extends Person> it = al.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}
//下限限定,列入collection中的addAll()
 public static void printColl(ArrayList <? super Student> al)
 //表示可以接收Student类型和Student父类型
	{
		Iterator<? super Person> it = al.iterator();

		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}

}

比较器泛型
class Person
{
	private String name;
	Person(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
}

class Student extends Person
{
	Student(String name)
	{
		super(name);
	}

}


class Student implements Comparable<Person>//<? super E>
{
	public int compareTo(Person s)
	{
		this.getName()
	}
}

class Comp implements Comparator<Person>
{
	public int compare(Person s1,Person s2)
	{

		//Person s1 = new Student("abc1");//
		return s1.getName().compareTo(s2.getName());
	}
}

TreeSet<Student> ts = new TreeSet<Student>(new Comp());
ts.add(new Student("abc1"));
ts.add(new Student("abc2"));
ts.add(new Student("abc3"));

4.总结
? 通配符。也可以理解为占位符。
泛型的限定;
? extends E: 可以接收E类型或者E的子类型。上限。
? super E: 可以接收E类型或者E的父类型。下限


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值