Re: <other> HashSet

光集合是不够应对所有问题的,于是乎泛型定义了规范。

  • A:泛型概述:
    限定集合存储的数据类型,Collection其中E代表 引用数据类型, 如果加上了该引用数据类型, 表示该集合中只能存储该类型对象, 或者该类型的子类对象.

  • B:泛型好处

    • 提高安全性(将运行期的错误转换到编译期)
    • 省去强转的麻烦
  • C:泛型基本使用

    • <>中放的必须是引用数据类型
  • D:泛型使用注意事项

    • 前后的泛型必须一致 ,或者后面的泛型可以省略不写 (1.7的新特性菱形泛型)

用起来的话就是下面这样

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

public class Demo1_Generic {

	public static void main(String[] args) {
		//demo1();
		//int[] arr = new byte[5];							//数组要保证前后的数据类型一致
		//ArrayList<Object> list = new ArrayList<Person>();	//集合的泛型要保证前后的数据类型一致
		//ArrayList<Object> list = new ArrayList<>();		//1.7版本的新特性,菱形泛型,前面定义了,后面不加表示和前面一致
		ArrayList<Object> list = new ArrayList<>();			//泛型最好不要定义成Object,没有意义
		list.add("aaa");
		list.add(true);
}

	public static void demo2() {
		ArrayList<Person> list = new ArrayList<Person>();
	//	list.add(110);
	//	list.add(true);
		list.add(new Person("张三", 23));
		list.add(new Person("李四", 24));
		
		Iterator<Person> it = list.iterator();
		while(it.hasNext()) {
			//System.out.println(it.next());
			
			//System.out.println(it.next().getName() + "..." + it.next().getAge());//next方法只能调用一次,如果调用多次会将指针向后移动多次
			Person p = it.next();			
			System.out.println(p.getName() + "..." + p.getAge());
		}
	}
	public static void demo1() {
		//这里编译通过,运行包ClassCastException(类转换异常)
		ArrayList list = new ArrayList();
		list.add(110);
		list.add(true);
		list.add(new Person("张三", 23));
		list.add(new Person("李四", 24));
		
		Iterator it = list.iterator();
		while(it.hasNext()) {
			Person p = (Person)it.next();			
			System.out.println(p.getName() + "..." + p.getAge());
		}
	}

}

到了这里就会涉及到增强for循环了,用案例来说吧。

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

public class Demo2_Foreach {
	
	public static void main(String[] args) {
		demo1();		
	}
	public static void demo1() {
		//基本数据类型数组的遍历
		int[] arr = {11,22,33,44,55};
		for (int i : arr) {
			System.out.println(i);
		}
		//集合的遍历
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		
		for (String string : list) {
			System.out.println(string);
		}
	}

}

很好用的一个集合遍历方法,不过不能删除元素,只是单纯的遍历。Arrays工具类中还有一个asList()方法,用来集合换数组。而Collection中的toArray(T[] a)方法就是泛型版的集合转数组了。
接下来就是HashSet了。
HashSet原理

  • 使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低, 哈希算法提高了去重复的效率,降低了使用equals()方法的次数

  • 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象

  • 如果没有哈希值相同的对象就直接存入集合

  • 如果有哈希值相同的对象, 就让哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存

当然有个问题,set是无序的,这时候就要用到LinkedHashSet的特点可以保证怎么存就怎么取还可以保证元素是唯一的。

import java.util.HashSet;
import java.util.Scanner;

public class Test1 {

/**
 * * 使用Scanner从键盘读取一行输入,去掉其中重复字符, 打印出不同的那些字符
 * aaaabbbcccddd
 * 
 * 分析:
 * 1,创建Scanner对象
 * 2,创建HashSet对象,将字符存储,去掉重复
 * 3,将字符串转换为字符数组,获取每一个字符存储在HashSet集合中,自动去除重复
 * 4,遍历HashSet,打印每一个字符
 */
public static void main(String[] args) {
	//1,创建Scanner对象
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入一行字符串:");
	//2,创建HashSet对象,将字符存储,去掉重复
	HashSet<Character> hs = new HashSet<>();
	//3,将字符串转换为字符数组,获取每一个字符存储在HashSet集合中,自动去除重复
	String line = sc.nextLine();
	char[] arr = line.toCharArray();
	
	for (char c : arr) {							//遍历字符数组
		hs.add(c);
	}
	
	//4,遍历HashSet,打印每一个字符
	
	for(Character ch : hs) {
		System.out.print(ch);
	}
	}

}

set集合中还有个TreeSet集合

import java.util.Comparator;
import java.util.TreeSet;

public class Demo3_TreeSet {

/**
 * @param args
 * TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一
 * 当compareTo方法返回0的时候集合中只有一个元素
 * 当compareTo方法返回正数的时候集合会怎么存就怎么取
 * 当compareTo方法返回负数的时候集合会倒序存储
 */
public static void main(String[] args) {		
	demo1();		
}
public static void demo1() {
	//因为TreeSet要对元素进行排序,那你排序的依据是什么,姓名还是年龄还是其它的,得告诉它,怎么告诉?
	//需要让Person类实现Comparable接口重写compareTo方法
	TreeSet<Person> ts = new TreeSet<>();
	ts.add(new Person("张三", 23));
	ts.add(new Person("李四", 13));
	ts.add(new Person("周七", 13));
	ts.add(new Person("王五", 43));
	ts.add(new Person("赵六", 33));
	
	System.out.println(ts);
	}

}
  • a.自然顺序(Comparable)

    • TreeSet 类的 add()方法中 会把存入的对象 提升为Comparable类型
    • 调用对象的 compareTo() 方法和集合中的对象 比较 (当前存入的是谁,谁就会调用compareTo方法)
    • 根据compareTo() 方法返回的结果 进行存储
  • b.比较器顺序(Comparator)

    • 创建TreeSet的时候 可以制定 一个Comparator
    • 如果传入了Comparator的子类对象, 那么TreeSet就会按照 比较器中的顺序排序
    • add()方法内部会自动 调用 Comparator接口 中compare()方法 排序
    • 调用的对象(就是当前存入的对象) 是 compare方法的第一个参数, 集合中的对象(已经添加进去的对象 )是compare方法的第二个参数
  • c.两种方式的区别

    • TreeSet构造函数什么都不传, 默认按照类中Comparable 的顺序(没有就报错ClassCastException)
    • TreeSet如果传入Comparator , 就优先按照Comparator

好了,先到这里。
ps:每日一词
满江红·相逢无语雨为酒

栖凤梧桐,听千语,夜长难许。花弄柳,不吾年纪,被风迎去。细日烟生云换替,半池闲绿游鱼聚。漫天舞、行客喜相逢,伤漂旅。

同生宴,当好句。杯欲酒,天将予。遣家书一段,远消千虑。浮若无依情自禁,相思难见相思故。月迷明,心念有嫦娥,衷肠付。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值