容器Set,List,Map

能够封装其他类对象的一个类,叫容器。容器中放入的是一些对象。
集合类型分三种:
Set,List,Map
Set:不区分元素顺序,不允许出现重复元素
List:区分元素顺序,允许包含重复元素
Map:映射中保存成对的“键-值”,映射中不能包含重复的键,每个键只能映射一个值。(哈希表)
在这里插入图片描述
实现类:HashSet, LinkList,ArrayList,HashMap

1、Collection接口—定义了存储一组对象的方法。其子接口Set和List分别定义了存储的方式
Collection接口中的方法:
(1)Object [] toArray()
容器不是数组,不能通过下标访问;若想当做数组用,利用Object[] bb=aa.toArray()转换为数组,调用bb[index]
(2)add,remove,addAll,removeAll,clear,boolean equals(Object o),int hashCode(),

2、Collection接口实现类的实例
所有添加到Collection容器中的对象都应该重写父类Object的toString方法。
将自己定义的类对象放入容器中,需要自己重写toString()方法。

import java.util.*;

public class TestCollection{
	public static void main(String[] args){
		Collection c = new LinkedList();
		c.add(new Student("zhangsan", 80));
		c.add(66.6);
		System.out.println(c);
	}
}

class Student 
{
	private String name;
	private int age;
	public Student(String name, int age){
		this.name = name;
		this.age = age;
	}
	//如果把toString方法注释掉了,则程序输出结果会有乱码
	public String toString()	{
		return name + " " + age; 
	}
}

3、List接口中的ArrayList,LinkedList
两者的区别:LinkedList双向链表实现。
在这里插入图片描述
4、Collections类,Collection接口
对于Collection接口实现的类,ArrayList、LinkedList本身并没有提供排序,倒置查找等方法,这方法是由Collections类实现,该类有很多public static 方法,可以直接对Collection接口的实现类进行操作。
Collections类常用方法
在这里插入图片描述
排序中的问题

import java.util.*;
class Student implements Comparable
{	private int id;
	private String name;	
	public Student(int id, String name)
	{
		this.id = id;
		this.name = name;
	}
	
	@Override                         //伪代码表示重写
	public String toString()
	{
		return id + "  " + name;  //1000张三   
		//System.out.println();
	}	
		@Override
	public int compareTo(Object o)  //父类的引用,比较标准的方法
	{
		Student st = (Student)o;		
		if (this.id == st.id)
			return 0;
		else if (this.id > st.id)
			return 1;
		else
			return -1;		
	}
}

public class TestList
{
	public static void main(String[] args)
	{
		List L = new ArrayList();   .//多态。当然将L转化数组 ,利用数组进行排序
		L.add(new Student(1000, "张三"));
		L.add(new Student(1003, "小娟"));
		L.add(new Student(1002, "王五"));
		L.add(new Student(1001, "李四"));
		Collections.sort(L);             //若没有compareTo(),比较标准不知道。默认将调用L中的compareTo方法。
		System.out.println(L);  
			}
}
//排序需要比较,利用到Comparabe接口

Comparable接口
compareTo方法的重写
在这里插入图片描述

Set接口
Set容器类中有HashSet,TreeSet(类)
问题:无序不重复,不需要实现Comparable接口,进行排序比较。输出的顺序跟添加顺序都不一样,且不允许容器中出现重复元素,对于Set中equals重写。比较对象中的内容,若相等返回true。不同内存,相同内容需要重写,实现true。
为了保证在HashSet容器中添加没重复,必须重写上述两种方法。
在这里插入图片描述
(1)重写的原因:
hashCode:两个对象不同,返回的hashCode不同。基本类型类的同样参数new出的对象的hashCode一样,默认都对hashCode进行了重写。
是否重写hashCode值。
将对象aa放入容器S中。
aa对象会根据aa对象里面的hashCode方法(返回某个值)找到对象存放的位置。再通过equals方法比较后面存放的元素是否有相同的元素。
在这里插入图片描述
TreeSet放入将自动排序。类实现Comparable接口,并重写compareTo方法。
(2)什么类必须向重写?
在这里插入图片描述
3、怎样重写?
equals重写注意将Object类对象ob强制转换为子类对象B bb=(B) ob,进行比较this.id==bb.i
hashCode中,内容一样哈希码一样,基本类型的,通过new Integer(i).hashCode()转换为相同。
返回当前基本类型数据对象的hashCode()方法
/*

Student类必须同时实现equals方法 和 hashCode方法 才可以保证在装入HashSet类时不会出现“重复”装入的情况
重新实现了equals方法 和 hashCode 方法 的正确的程序

*/

import java.util.*;

public class TestHashSet
{
public static void main(String[] args)
{
Collection c = new HashSet();
c.add(new Student(1001, “张三”));
c.add(new Student(1002, “李四”));
c.add(new Student(1003, “王五”)); //10行
c.add(new Student(1003, “王五”));
c.add(new Student(1003, “王五”));
c.add(new Student(1003, “王五”));
c.add(new Student(1003, “王五”)); //14行

	Iterator i = c.iterator();
	while (i.hasNext())
	{
		System.out.println(i.next());
	}
}

}

class Student
{
private int num;
private String name;

public Student()
{
}

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

public String toString()
{
	return "学号: " + this.num + ",  姓名: " + name;
}

public boolean equals(Object o)
{
	Student s = (Student)o;
	
	return this.num==s.num && this.name.equals(s.name);
}
public int hashCode()
{
	//return num; //如果你设定的学生信息中学号是唯一的,则可以直接用num来作为哈希码
	return num * this.name.hashCode();
}

}

Iterator 接口
由于数据的存储方式不同,遍历元素较为麻烦。数组,链表,树。。访问不同
如何忽略存储数据的差别,进行遍历。按照同一方式访问他们的元素

方法
在这里插入图片描述
boolean hasNext():游标不动,用来判断当前游标后面是否存在元素,若存在,返回为真,否则为假、初始为值为第一个元素的前面位置。
object next():先返回当前游标右边的元素,然后游标后移一个位置
void remove();

import java.util.*;

public class TestIterator_1
{
	//可以遍历所有Collection接口的实现类
	public static void showCollection(Collection c)
	{
		Iterator it = c.iterator();      //Collecion中有Iterator()方法,it就是指针,通过指针调用hasNext方法,it指向第一                      
		                                           //个元素的指针。it.next---it++; it指针可以指向c容器中的元素
		while (it.hasNext())
		{
			System.out.println(it.next());
		}
	}

	public static void main(String[] args)
	{
		ArrayList al = new ArrayList();
		al.add("one");
		al.add(22);
		al.add(new Point(1,1));
		System.out.println("a1 容器的内容是:");
		showCollection(al);
		
		HashSet hs = new HashSet();
		hs.add("one");
		hs.add(22);
		hs.add(new Point(1,1));
		System.out.println("hs容器的内容是:");
		showCollection(hs);
	}
}

class Point
{
	private int i, j;	
	public Point(int i, int j)
	{
		this.i = i;
		this.j = j;
	}
	public String toString()
	{
		return "[" + i + ", " + j + "]";
	}
}

3、Map
为了更加方便的查找某个元素,给出关键字,一次性找出
内部实现:根据每个元素的关键字存放位置,放置元素。给出关键字,计算元素存放的地址。
每个元素映射地址不同,最后映射完,每个元素的地址是连续的。完美情况是这样,设计出来很困难。实际中每个元素之间的地址相差较大,浪费空间。
存在的问题:
关键字出现映射地址一样,hash冲突。
关键字对应的映射地址超出了元素存放的内存区间,没有其地址。
map映射地址数据存放的空间浪费
避免冲突;存储空间内存大小设计与 存放数据大小匹配
哈希因子不能过高,为了避免冲突,但检测到快满时,就会扩充内存。
为了避免哈希冲突,存放方式Hash表。根据关键字找位置,即使两个关键字映射为同样的hashCode,但是仍然比较看看后面是否f,将再继续放入。
Map的实现类HashMap,遍历所有元素利用方法keySet()方法,

import java.util.*;

class Student
{
	private int id;
	private String name;
	private int age;
	
	public Student()
	{
	}
	
	public Student(int id, String name, int age)
	{
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()
	{
		return this.name.hashCode()*id*age;
	}	
	
	public boolean equals(Object o)
	{
		Student s = (Student)o;
		return this.name.equals(s.name) && this.id==s.id && this.age==s.age;	
	}	

	public String toString()
	{
		return id + "  " + name + "  " + age;
	}
}

public class TestHashMap_2
{
	public static void main(String[] args){
		HashMap hm = new HashMap();
		hm.put(1001, new Student(1001, "zhangsan", 20));  //自动封装new integer(1001),1001为将值转换为自动转为integer对象,容器中必须存的是对象
		hm.put(1003, new Student(1003, "lisi", 30));      //自动封装
		hm.put(new Integer(1004), new Student(1004, "wangwu", 10));
		hm.put(1002, new Student(1002, "baichi", 20));    //自动封装
		
		//遍历所有的元素
		System.out.println("hm容器中所有的元素是:");
		Set s = hm.keySet();  //获取到当前容器键的集合,实际就是Integer对象的集合
		Iterator it = s.iterator();
		while (it.hasNext()){
			//int Key = (Integer)it.next();   // (Integer) 不能省,这里key,定义方法it.next()返回object类型转换为子类, 利用了自动拆分技术      
			Integer kk = (Integer)it.next();  //kk变量就可以,不是关键字
			System.out.println(hm.get(kk));
		}
		
		System.out.println("直接查找某一元素");
		System.out.println( hm.get(1003) );	
		System.out.println( hm.get(1005) );	  //如果找不到 则直接返回null,而不是抛出异常 			
	}
}

泛型:限制指定某一时刻,某一个容器放置的元素类型。
对于Iterator,说明内部数据可以是任意的,但是对于具体某一次运行,可以设定对象类型
对于接口以及实现接口的类都需要指定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值