资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

J2EE 快速入门之第二章 Set集合详解

Java 更新时间: 发布时间: 计算机考试归档 最新发布

J2EE 快速入门之第二章 Set集合详解

一:Collection.remove()与ArrayList.remove()方法的不同            1. Collection 中只能根据元素移除            2.ArrayList 可以根据元素删除 , 也可以根据下标删除

二:完成ArrayList去重的案例    观察以下代码 , 并得出代码执行后的结果
Dog d = new Dog("小黑",5);
List ls=new ArrayList();
ls.add(d);
ls.add(d);
ls.add(d);
System.out.println(ls.size());
    得出结果后推导原因: List 接口的特点之一就是可重复      问:如何在ArrayList出完成去除重复值的功能      答: 使用 contains方法进行判断,判断新的集合newLs是否包含指定的元素,如果包含,那么不添加新集合中,如果不包含,那么添加到 新集合中  
           
public static List singleList(List oldLs) {
List newLs = new ArrayList();// 去除重复值之后的集合
for (Dog d : oldLs) {// 遍历需要去除重复值的集合
if (!newLs.contains(d)) {// 如果在新集合中不存在
newLs.add(d);// 加入到新集合中
}
}
return newLs;
}
写完方法之后再调用之前的案例查看结果 :
Dog d = new Dog("小黑",5);
List ls = new ArrayList();
ls.add(d);
ls.add(d);
ls.add(d);
List newLs = singleList(ls);
System.out.println("集合:"+newLs);
System.out.println("长度:"+newLs.size());
输出结果:
集合:[Dog [name=小黑, age=5]]
长度:1
换种方式在试:
Dog d1 = new Dog("小黑",5);
Dog d2 = new Dog("小黑",5);
Dog d3 = new Dog("小黑",5);
List ls = new ArrayList();
ls.add(d1);
ls.add(d2);
ls.add(d3);
List newLs = singleList(ls);
System.out.println("集合:"+newLs);
System.out.println("长度:"+newLs.size());



输出结果 :
集合:[Dog [name=小黑, age=5], Dog [name=小黑, age=5], Dog [name=小黑,
age=5]]
 长度:3
  • == 与 equals 的区别:
      == 比较的对象在内存中的地址       equals 比较的是对象的内容(通过重写方法,可以自定义判断规则) 在没有重写 equals 的情况下 默认使用的是 Object 类的 equals 比较的是对象在内存中的 地址 重写 Dog 的 equals 方法 :      
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
重写了equals方法,判断只要名字相同,就认为是同一只狗
重新执行上面的代码,输出结果:
集合:[Dog [name=小黑, age=1]]
长度:1
讲解原理:         contains 方法与 remove 方法的内部都是根据对象的 equals 方法来做判断的  问: 除了这种方式之外,有没有别的方法能够去除重复值?   答: 引入 Set 集合 三:Set接口介绍            Set 接口是继承自 Collection 的子接口,特点:元素不重复
Set set = new HashSet();
set.add("jack");//第一个jack
set.add("rose");
set.add("alien");
set.add("jack");//第二个jack
for (String s : set) {
System.out.println(s);
}
输出结果 :
rose
 jack
 alien

四:Set接口下的实现类
  • HashSet
  • 无序
Set set = new HashSet();
set.add("a");
set.add("d");
set.add("c");
set.add("b");
for (String s : set) {
System.out.println(s);
}

输出结果:

 a
 b
 c
 d

     要注意强调无序指的是插入的顺序与取出的顺序不一致(从输出结果可以看到) , 原因:               在对象进入 HashSet 内部时 , 会使用对象内部 HashCode 方法计算 hash 值后自动进行排序, 所以读取的是经过内部排序后的数据,所以存入的顺序会与取出的顺序有不同(内部通过排序重 新整理了元素的位置),并且在数据没变的情况下,每次数据输出结果都是一样的顺序
  • 不重复
         HashSet 底层数据结构是 哈希表 , HashSet 不是线程安全的,但是效率高,同时集合元素可以是 null 查看源码:
private transient HashMap map;
public HashSet() {
map = new HashMap<>();
}
当我们在调用 add 方法往 HashSet 中添加元素时:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap源码:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
原理:                  在 HashSet 中放入元素的时候 , 相当于将元素放在了一个 Map 哈希表中,在 Map这种哈希表 中,分为键值对形式存储。在上面存入元素时,该元素的 hash 值 hash(key) 会被作为键,而元素 则会被作为值。 HashSet 集合中如何判断两个元素相等的标准:      通过两个对象 hashCode() 方法拿到哈希值,如果两个哈希值相同,再调用 equals() 方法比较 如果都相同,则认定为同一个元素,无法存入 重点: HashSet 保证元素唯一性是靠元素重写 hashCode() 和 equals() 方法来保证的,如果不重写则无法保证
  • 代码演示
1.重写hashCode()方法 这个方法的作用就是返回对象的hash值
@Override
public int hashCode() {
System.out.println("调用了hashCode");//调用时打印
return age;//该对象的hash值就是他的年龄
}
@Override
public boolean equals(Object obj) {
System.out.println("调用了equals");//调用时打印
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) 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;//只要名字相同 则equals返回真
}
Dog d1 = new Dog("小黑",1);
Dog d2 = new Dog("小黑",1);
Dog d3 = new Dog("小白",1);
HashSet set = new HashSet();
  • 将 d1 添加到集合中
set.add(d1)
   控制台输出:              调用了 hashCode 原因:         往集合中添加 d1 元素时 , 集合内没有 hash 值为 1 的其他元素 , 所以只调用了 hashCode() 来获取 对象的 hash 值
  • 将 d2 添加到集合中
set.add(d2);
  • 控制台输出:
              调用了 hashCode                调用了 equals 原因:       往集合中添加 d2 元素时 , 集合内已经有一个 d1 了 , 并且它的 hash 值也为 1       讲解判断规则 : 两个哈希值相同,再调用 equals() 方法比较 提问:这个时候集合中长度 ?                 set 集合的长度 :1
  • 将 d3 添加到集合中
set.add(d3);
         调用了 hashCode          调用了 equals 问:此处的集合长度?        set 集合的长度 :2 原因讲解:     hash 值虽然相同,但是 equals 时得到的结果不对应,所以不被认为是相同的元素,所以添加成 功 注意:     判断元素是否存在,以及删除等操作,用作判断的条件同样是 hashCode()+equals() 方法 五:TreeSet             TreeSet 是一个有序的集合,它的作用是提供有序的 Set 集合(没有重复值)
  • 有序
          底层数据结构是二叉树,集合中元素唯一 , 并且可以对元素进行排序
TreeSet set=new TreeSet();
set.add("jack");
set.add("rose");
set.add("alien");
for (String s : set) {
System.out.println(s);
}
输出结果:
alien
 jack
 rose
  • 排序方式:自然排序
          让需要排序的类实现 Comparable 接口,重写方法 (因为 String实现了这个接口,所以上面的数据是有序的)
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
返回值:
  1. 如果返回值>0,他大
  2. 如果返回值=0,相等
  3. 如果返回值<0,我大
将代码修改为按照年龄排序:
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return this.age-((Dog)o).getAge();
}
代码:
Dog d1 = new Dog("小黑", 23);
Dog d2 = new Dog("小白", 35);
Dog d3 = new Dog("小青", 18);
Dog d4 = new Dog("小绿", 22);
TreeSet ts = new TreeSet();
ts.add(d1);
ts.add(d2);
ts.add(d3);
ts.add(d4);
for (Dog d : ts) {
System.out.println(d);
}

输出结果:
 Dog [name=小青, age=18]
 Dog [name=小绿, age=22]
 Dog [name=小黑, age=23]
 Dog [name=小白, age=35]
如果年龄相同,则可以按照其他条件来排序,比如:名字
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Dog d=(Dog)o;
int num=this.age-d.getAge();
if(num==0) {
return this.name.compareTo(d.getName());
}
return num;
}
  • 比较器排序
          使用公安局给出数据的例子,来提出怎么实现这些数据的排序,引出比较器排序。           定义一个比较器(实现 Comparator 接口):
public class DogComparator implements Comparator{
}
重写compare方法:
@Override
public int compare(Dog o1, Dog o2) {
return 0;
}
按照年龄排序
@Override
public int compare(Dog o1, Dog o2) {
return o1.getAge()-o2.getAge();
}
在年龄相同的时候(主条件),可以根据名字来排序(次条件)
@Override
public int compare(Dog o1, Dog o2) {
int x=o1.getAge()-o2.getAge();
if(x==0) return o1.getName().compareTo(o2.getName());
return x;
}

在初始化TreeSet的时候将我们写好的比较器传入就可以了(提醒要注意):

Dog d1 = new Dog("小黑", 23);
Dog d2 = new Dog("小白", 35);
Dog d3 = new Dog("小青", 18);
Dog d4 = new Dog("小绿", 22);
TreeSet ts = new TreeSet(new DogComparator());//指定比较器
ts.add(d1);
ts.add(d2);
ts.add(d3);
ts.add(d4);
for (Dog d : ts) {
System.out.println(d);
}
输出结果:
Dog [name=小青, age=18]
 Dog [name=小绿, age=22]
 Dog [name=小黑, age=23]
 Dog [name=小白, age=35]
问:如何将集合中的排列改成从大到小?
比较优先级:比较器排序大于自然排序
  • 二叉树
特点:左子树的键值小于根的键值,右子树的键值大于根的键值

六:泛型
  • 为什么会需要泛型
演示 Object 集合的转换报错问题:
List ls=new ArrayList();
ls.add(1);
ls.add("a");
for (Object o : ls) {
System.out.println((Integer)o);
}
          如果集合对于元素类型没有限制,对于取数据的人来说,还需要先转为对应的类型再来操作,并且可能会报异常           引出泛型的作用,在编译时期就限制数据类型
package com.zking.collection01.util;

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

public class Demo2 {

	public static void main(String[] args) {
		//泛型:以类型作为参数的类就叫泛型
		//作用:提供程序的健壮性、简化代码
		//泛型的默认类型为Object
		//泛型是从jdk1.5之后推出的
		
		List lst=new ArrayList<>();
		//lst.add("zs");
		
		lst.add(1);
		lst.add(2);
		lst.add(7);
		lst.add(6);
		
		//获取迭代器
		ListIterator it = lst.listIterator();
		//循环遍历
		while(it.hasNext()) {
			//获取集合中的元素(先移动下标)
			//Object val = it.next();
			//转换数据类型
			//int num=Integer.parseInt(val.toString());
			Integer num = it.next();
			//获取偶数数据
			if(num%2==0)
				System.out.println(num);
		}
		
		
		//装箱
		int a=1;
		Integer num=new Integer(a);
		//拆箱
		int b = num.intValue();
		
		
	}
}







七:提问
  • 如何去除ArrayList中的重复值?
  1. 编写代码
  2. List与Set的转换
  • HashSet与TreeSet的区别?
  1. 底层数据结构
  2. 顺序
  • TreeSet是有序的吗?
  1. 插入顺序
  2. 数据顺序
  • TreeSet在排序时如何比较元素?
  1. 自然排序
  2. 选择器排序
  • HashSet如何检查重复?
  1. hashCode()+equals()
转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/939397.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【J2EE 快速入门之第二章 Set集合详解】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2