Java-集合框架List_Set

集合框架List_Set

1.什么是集合框架List_set

1.其实这种集合框架Java已经为我们写好了,List和Set都是Java已经写好的数据结构

2.List和Set是接口:我们主要用接口下面实现类

3.ArrayList
3.1 ArrayList介绍

1.内部基于数组实现的一个集合类。查询比较快,添加和删除相对比较慢 2.猜ArrayList中会有哪些功能(方法):
添加、删除、查询、插入、修改。。。 3.不是同步的(存在线程安全问题)

遍历方式
1.使用普通的for循环

ArrayList bag = new ArrayList();
bag.add("电脑");
bag.add(200);
bag.add("鼠标");
bag.add("小人书");
bag.add("教材");
bag.add("牛奶");
		
for(int i=0;i<bag.size();i++){
	System.out.println(bag.get(i));
}

2.增强for循环(foreach)
for(源中的数据类型 变量名 : 源){
}
注意:源可以是数组或者集合(Iterable的实例)
3.使用迭代器进行遍历
Iterator 就是一个迭代器(也是一个接口)其中的方法如下:
boolean hasNext() 判断是否有下一个元素,如果返回true表示有下一个;
Object next() 调用一次获得一个元素(每调用一次指针会向后移动一个);
void remove() 会从迭代器指向的结合容器中删除一个元素
代码清单:

ArrayList bag = new ArrayList();
bag.add("电脑");
bag.add(200);
bag.add("鼠标");
bag.add("小人书");
bag.add("教材");
bag.add("牛奶");
		
//使用迭代器遍历集合ArrayList   bag获得一个迭代器
Iterator it = bag.iterator();
while(it.hasNext()){
	System.out.println(it.next());
}

迭代器注意事项
1.如下结果:只遍历了一次,为什么?

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

原因:上面两个while使用的是同一个迭代器,第一个while循环完毕就把指针移动到末尾了,所以第二个while不会执行了

2.双向迭代器

Iterator 单项的迭代器接口,从左到右依次获得数据,判断是否有下一个;获得下一个
|-- ListIterator 双向的迭代器接口,它的主要方法如下:
Iterator中有的它也有;
boolean hasPrevious() 判断是否有上一个;
Object previous() 获得上一个元素;

代码清单:

ArrayList bag = new ArrayList();
bag.add("电脑");
bag.add(200);
bag.add("鼠标");
bag.add("小人书");
bag.add("教材");
bag.add("牛奶");
// 获得双向的迭代器
ListIterator iterator = bag.listIterator();
while(iterator.hasNext()){
	System.out.println(iterator.next());
}
System.out.println("-----------------");
while(iterator.hasPrevious()){
	System.out.println(iterator.previous());
}

4 ListList介绍

1、 内部是基于链表结构实现的。添加和删除比较快,查询相对ArrayList比较慢 2、
内部相对于ArrayList而言多了一些操作头和尾的方法 3、 可以充当队列,堆栈 4、 不是线程安全的(同步的)

5.自定义不重复元素的容器
2.1 如何自定义

1.现在需要我们自己设计一个容器类,不能够添加重复元素(如果元素重复了就添加不进去) 2.在前面我们设计的基于数组的自定义容器类的基础上改版
3.需要在add方法内部判断重复 4.如何判断: (1)每一次调用add会传入一个参数: 用户希望添加的元素 ele
(2)遍历内部的数组,判断数组中是否包含ele

2.2 代码实现

public boolean add(Object ele){
	for (Object object : data) {
		if(ele.equals(object)){
			return false;
		}
	}
	if(size == data.length){//扩容[ +10 ]新数组  将久数组值,复制到新数组
		Object[] newArr = new Object[size+20];
		System.arraycopy(data, 0, newArr, 0, size);
		data = newArr;
	}
	data[size] = ele;
	size++;
   return true;
}

6.HashSet
6.1 HashSet介绍

1.不能够添加重复元素 2.无序(不保证和添加和打印顺序一致


初体验

HashSet hs = new HashSet();
hs.add("A");
hs.add("D");
hs.add("C");
hs.add("B");
hs.add("B");
		
System.out.println(hs.size());
System.out.println(hs);

如何判断重复的

1.通过添加进去的元素的hashCode+eqauls 两者进行比较 2.如果两个对象的hashCode相等 并且
两个对象调用equals结果是true 才认为两个元素重复

验证上面的规则
1.打印上面示例中的元素的hashCode和equals的结果
2.尝试自定义类,覆写hashCode 和 equals 这两个方法中的代码随便写
(1)尝试修改两个方法的值来测试容器中添加了几个对象

class Student{
	String name;
	int age;
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int hashCode() {
		return new Random().nextInt();//随机值,出现不同值的可能性很大
	}
	@Override
	public boolean equals(Object obj) {
		return true;//对象比较结果为true
	}
@Override
public String toString(){
    return name+"-"+age
}
}
1.测试代码
HashSet hs = new HashSet();
//地址值      对象属性是否一致{现实}
Student stu1 = new Student("OOO",18);
Student stu2 = new Student("OOO",18);
//stu1  stu2  HashCode值是否一致  equals比较的结果,决定是否是同一个对象,决定能否添加到hs
hs.add(stu1);
hs.add(stu2);
System.out.println(hs.size());
System.out.println(hs);

实际开发情况分析

1.覆写的时候应该参考实际业务中的比较规则,例如姓名,年龄等,根据对象属性判断对象是否重复

@Override
public int hashCode() {
	return name.hashCode()+age;//由属性来决定对象的hash值
}
@Override
public boolean equals(Object obj) {
	Student stu = (Student)obj;
	return this.name.equals(stu.name)&&this.age == stu.age;
}

2.自动覆写HashCode及Equals方法参考学习Java怎么写的

hashCode
@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + age;
	result = prime * result + ((name == null) ? 0 : name.hashCode());
	return result;
}
(1)hashCode自动覆写分析
equals
@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Student other = (Student) obj;
	if (age != other.age)
		return false;
	if (name == null) {
		if (other.name != null)
			return false;
	} else if (!name.equals(other.name))
			return false;
	return true;
}

7.TreeSet
4.1 TreeSet介绍

1.无序:不保证(不记录)我们的添加顺序;
2.不重复:不能够添加重复元素(如何判断重复的呢?
3.感觉内部存储有一定的顺序
注意:TreeSet一旦添加了第一个元素后就不能添加其它数据类型的元素了,只能添加相同数据类型的元素,除非将容器中所有的元素全部清空,才能添加新的数据类型的元素

4.2 简单体验
体验1:不重复及不保证添加顺序和打印顺序一致

TreeSet ts = new TreeSet();
ts.add("B");
ts.add("A");
ts.add("C");
ts.add("C");
System.out.println(ts.size());
System.out.println(ts);

1.结果: 虽然打印结果的顺序和添加顺序可能不一致,但是感觉结果是有某种规则排序的
2.说明String类也实现了Comparable接口,String对象可以调用compareTo方法

体验2:添加了一种类型不能在添加其他类型

TreeSet ts = new TreeSet();
ts.add("B");
ts.add("A");
ts.add("C");
ts.add("C");
ts.add(10);
System.out.println(ts.size());
System.out.println(ts);
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at java.lang.Integer.compareTo(Unknown Source)
	at java.util.TreeMap.put(Unknown Source)
	at java.util.TreeSet.add(Unknown Source)
	at cn.itsource._07TreeSet.TestTreeSet.main(TestTreeSet.java:12)

1.结果:居然不能够放不同的类型,但是编译没有错

体验3: 添加自定义的类的对象 Student对象

TreeSet ts = new TreeSet();
Student stu1 = new Student("王者",18);
ts.add(stu1);
System.out.println(ts.size());
System.out.println(ts);
Exception in thread "main" java.lang.ClassCastException: cn.itsource._07TreeSet.Student cannot be cast to java.lang.Comparable
	at java.util.TreeMap.compare(Unknown Source)
	at java.util.TreeMap.put(Unknown Source)
	at java.util.TreeSet.add(Unknown Source)
	at cn.itsource._07TreeSet.TestTreeSet.main(TestTreeSet.java:9)

4.3 TreeSet的结构(存储原理)分析

1.TreeSet内部是按照大小进行排序的,大小有对象与对象之间比较进行决定的
2.设计TreeSet之前:Java设计了一个接口Comparable接口,其中提供了对象之间比较的方法CompareTo
3.TreeSet会调用对象的CompareTo方法,比较对象,所以我们放入的对象需实现Comparable

4.4 自然排序与定制排序(比较器)

什么是自然排序

1.例如:大家排队,按照高矮个排队,那么同学们自己相互之间就能进行对比,每个对象具备自我比较判断的能力,称之为自然排序
Comparable中API文档中的描述: 2.此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的
compareTo 方法被称为它的自然比较方法 理解:
3.如果一个类实现了Comparable接口,可以认为这个类的对象具有自然排序的能力(本质就是这个对象可以调用比较的方法compareTo),这种比较和排序的规则就是自然排序

@Override
public int compareTo(Object o) {
	if(o==null){
		return 0;
	}
	Student stu = (Student)o;
	if(this.age>stu.age){//如果大于的时候返回负数表示降序,返回负数表示升序
		return -1;
	}else if(this.age<stu.age){//如果大于的时候返回负数表示降序,返回负数表示升序
		return 1;
	}else{//如果年龄不大于也不小于说明等于,那么有名字来决定对象是否相同String已经写好排序规则
		return this.name.compareTo(stu.name);
	}
}

测试代码

TreeSet ts = new TreeSet();
Student stu1 = new Student("XXX",20);
Student stu2 = new Student("XXX",20);
ts.add(stu1);
ts.add(stu2);
System.out.println(ts.size());
System.out.println(ts);
1
[Student [name=XXX, age=20]]
定制排序(比较器)Comparator

1、什么是定制排序

定制排序,相当于给容器提供了一个裁判:例如操场就是一个容器,那么体育老师就是这个裁判,每个同学进入操场同学们相互之间可以比较谁比较帅,或者不可以比较谁帅都可以,有了老师这个裁判,老师可以负责比较每一位同学

2、为什么需要定制排序

(1)原来的比较规则不符合所有人的使用需求 (2)不存在比较规则的对象,无法放入容器,我可以给容器提供定制比较器

3、定制排序如何实现

(1)Comparator 是一个比较器的接口(标准),必须得有进行比较的方法 :compare(Object o1,Object o2);
(2)自定义一个类实现Comparator接口,其中写比较规则 —> 比较器的模板,我们现在需要的是一个具体的比较器对象

public class MyComparator implements Comparator{
	@Override
	public int compare(Object o1, Object o2) {
		if(o1==null||o2==null){//判断,若两个有一个为null都直接返回
			return 0;
		}
		if(o1 instanceof Student && o2 instanceof Student){//如果类型匹配才转换
			Student stu1 = (Student)o1;
			Student stu2 = (Student)o2;
			if(stu1.age>stu2.age){//先判断年龄后判断姓名
				return 1;
			}else if(stu1.age<stu2.age){
				return -1;
			}else{
				return stu1.name.compareTo(stu2.name);
			}
		}
		return 0;
	}
}

测试代码

MyComparator mc = new MyComparator();
TreeSet ts = new TreeSet(mc);
Student stu1 = new Student("XXX",19);
Student stu2 = new Student("OOO",18);
Student stu3 = new Student("YYY",18);
Student stu4 = new Student("ZZZ",18);
Student stu5 = new Student("QQQ",18);
ts.add(stu1);
ts.add(stu2);
ts.add(stu3);
ts.add(stu4);
ts.add(stu5);
System.out.println(ts.size());
System.out.println(ts);
 5
[OOO-18, QQQ-18, YYY-18, ZZZ-18, XXX-19]

4.5 TreeSet判断重复的标准小结
1、如果采用的是自然排序调用对象的compareTo方法,如果返回0 表示相等;
大于且返回正数,升序排列 => 小于且返回负数,升序排列 对应
大于且返回负数,降序排列 => 小于且返回正数,降序排列 对应
2、如果使用的定制排序(比较器),调用比较器的方法compare 返回0 表示相等;
大于且返回正数,升序排列 => 小于且返回负数,升序排列 对应
大于且返回负数,降序排列 => 小于且返回正数,降序排列 对应
8.Collection体系

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值