Set接口:Set集合继承Collection集合
Set:底层的数据结构是一个哈希表,保证元素唯一,元素不重复
通过子实现类HashSet集合去实例化,Hashset集合底层是HashMap集合的实例!
//利用ser集合存储字符串元素并遍历,证明元素唯一
Eg:
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
public static void main(String[] args) {
Set<String> set=new HashSet<String>();
set.add("faker");
set.add("Uzi");
set.add("Margen");
set.add("Uzi");
set.add("Uzi");
set.add("Uzi");
for(String s:set){
System.out.println(s);
}
}
}
输出结果为
Uzi
Magren
faker
证明了set集合元素的唯一性,元素不重复.
Set集合的子实现类
实现Set接口,由哈希表(实际是一个hashMap)支持.不保证set的迭代顺序,不能保证顺序不发生变化.
HashSet集合的add方法,底层依赖于双列集合HashMap<K,V>的put(K key,V value)实现的
put(K key,Vvalue):这个方法底层又依赖于equals()和hashCode()方法.首先比较地址值是否相同,当地址值相同后再用equals方法比较值是否相同.此时保存的是String类型.因为equals方法默认比较的是地址值.重写后比较的是值是否相同.String类型默认重写了equals方法.当内容相同时,返回第一次存储的元素,以此保证元素的唯一性.
put(K key,V value)键值对
一个对象key 对应一个value 都存储值, 一个key和value对应一个地址值.
import java.util.HashSet;
public class HashDemo {
public static void main(String[] args) {
HashSet<String> hs=new HashSet<String>();
hs.add("RNG");
hs.add("RNG");
hs.add("RNG");
hs.add("WE");
hs.add("WE");
hs.add("SKT");
for(String s:hs){
System.out.println(s);
}
}
}
需求:使用Hash存储自定义对象并遍历
List与Set集合的区别?
Set集合:元素唯一,无序性(存取不一致)
List集合:元素可以重复,且有序(存取一致)
创建学生对象:
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Student>hs=new HashSet<Student>();
Student s1=new Student("小虎",22);
Student s2=new Student("小狗",20);
Student s3=new Student("大魔王",21);
Student s4=new Student("五五开",23);
Student s5=new Student("小虎",22);
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
for(Student s:hs){
System.out.println(s.getName()+"--"+s.getAge());
}
}
}
Student类必须重写equals()方法和HashCode()
输出结果:
大魔王--21
五五开--23
小狗--20
小虎--22
HashCode返回地址值. 当值相同时,地址值也相同
public class HashSetDemo1 {
public static void main(String[] args) {
System.out.println("Uzi".hashCode());
System.out.println("Faker".hashCode());
System.out.println("Margrn".hashCode());
System.out.println("AAA".hashCode());
System.out.println("AAA".hashCode());
}
}
LinkedHashSet集合:由哈希表保证元素的唯一性,链接列表保证元素的有序性.
import java.util.LinkedHashSet;
public class LinkHashSetDemo {
public static void main(String[] args) {
LinkedHashSet<String>link=new LinkedHashSet<String>();
link.add("Uzi");
link.add("Uzi");
link.add("Uzi");
link.add("faker");
link.add("faker");
link.add("Margin");
for(String s:link){
System.out.println(s);
}
}
}
输出为:
Uzi //该集合保证数据的唯一性和有序性
faker
Margin
Random:产生一个随机数的类:
构造方法:publicRandom()创建一个新的随机数生成器
成员方法:public intnextInt():有随机数生成器调用方法,随机数的范围在
int类型的范围之内
public int nextint(int n):生成随机数的范围:[0,n):使用比较多
包含左,不包含右
eg:
import java.util.Random;
public class RandomText {
public static void main(String[] args) {
Random r=new Random();
for(int x=0;x<10;x++){
int number=r.nextInt();
int number1=r.nextInt(20)+1;
// System.out.println(number);
System.out.println(number1);
}
}
}
练习:生成10个1到20之间的随机数,不能重复.
1. 创建一个随机数生成器
2. 使用ArrayList存储:类型Integer
3. 定义统计变量count
4. 判断如果统计变量小于10 通过随机数获取1-20间的数
判断集合是否有 ,不包含则添加这些随机数,不包含,添加集合count++
5. 遍历集合
eg:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Random;
public class RandomText1 {
public static void main(String[] args) {
Random r=new Random();
//创建集合
ArrayList<Integer>arr=new ArrayList<Integer>();
int count=0;
while(count<10){
int number=r.nextInt(20)+1;
if(!arr.contains(number)){ //判断是否包含
arr.add(number);
count++;
}
}
for(Integer i:arr){
System.out.print(i+" ");
}
}
}
TreeSet:Set集合中重点
TreeSet集合底层依赖TreeMap的实例,TreeMap<K,V>依赖于红黑树实现
两种方法: 自然排序 比较器排序
取决于使用的构造方法:
自然排序:
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
//public TreeSet():无参构造:根据其元素的自然顺序进行排序
TreeSet<Integer> ts = new TreeSet<Integer>();
//20,18,23,22,17,24,19,18,24
ts.add(20);// Integer i =Integer.valueOf(20) ;
ts.add(18) ;
ts.add(23) ;
ts.add(22) ;
ts.add(17) ;
ts.add(24) ;
ts.add(19) ;
ts.add(18) ;
ts.add(24) ;
for(Integer i : ts){
System.out.print(i+ " ");//17 18 19 20 2223 24 :唯一并且排序:自然排序(升序排序)
}
}
}
输出结果: 17 18 1920 22 23 24
红黑树结构:二叉树结构,一种自平衡的二叉树结构
红黑树结构在存储元素时,第一次存储元素作为根节点.后面以此存储元素,
与根节点进行比较,如果小了,左孩子. 大了,右孩子.
当相等时,不用管.
排序:依赖于TreeMap<k,V>中的put<K key, V value>
按照自然顺序输出
对于TreeSet集合要实现自然排序,那么该集合该集合中存储自定义类型必须实现一个接口:Comparable,并且重写该接口中的compareTo()方法
使用TreeSet集合存储自定义对象并遍历.
按照学生的年龄从小到大进行排序:主要条件
对于自定义对象什么情况下保证元素是唯一的
成员变量的值相同,认为是同一个元素
次要条件 姓名内容长度
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
//创建TreeSet集合对象
TreeSet<Student> ts = new TreeSet<Student>() ;//
//创建学生对象
Student s1 = new Student("wuwenlong", 20) ;
Student s2 = new Student("yangqilong", 21) ;
Student s3 = new Student("dengcong", 22) ;
Student s4 = new Student("pengkai",25) ;
Student s5 = new Student("yangxiaozhou", 18) ;
Student s6 = new Student("qiyuan", 22) ; ;
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
for(Student s : ts){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
Student类
要实现自然排序,就必须实现Compareable接口
Student重写compareTo方法
@Override
public int compareTo(Students) {
//主要条件:按照年龄从小到大进行排序
int num =s.age - this.age ;
//当num==0认为年龄一样要,给出自然条件,比较长度
int num2 = num==0 ? this.name.compareTo(s.name): num ;
return num2 ;
}
}
比较器排序
依赖于构造方法: public TreeSet()Compare<E> comparator
两种方法实现比较器排序.
Comparator接口作为形参,需要接口的子实现类
方式一:自定义一个类,类实现CompareTo接口,作为子实现类
方式二:可以使用接口的匿名内部类来实现:开发中,由于减少代码书写量,不需要自定义接口的子实现类,直接这种格式!
格式
new 接口名或者类名(){
重写方法() ;
}
1.通过Comparetor接口的子实现类实现
Eg:
public class MyComparatorimplements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// 按照学生姓名长度从小到大进行排序
int num =s1.getName().length() - s2.getName().length() ;
//次要条件:姓名长度一样,还要比较姓名的内容是否一样
int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num;
//姓名长度和内容都一样,还需比较两个人的年龄是否一样
int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
return num3 ;
}
}
2.匿名内部类
TreeSet<Student> ts = newTreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//里面写条件
}
}) ;
练习题: 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
首先定义一个Student类 提供姓名,语文,数学,英语等成员变量.并且提供一个getsun()
获取总分的方法.
创建创建TreeSet集合对象:TreeSet<Student>(Comparator<Student>com)集合
写出条件
录入成绩 for循环输出
Eg:
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class TreeSetDemo1 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(newComparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s2.getSum() - s1.getSum();//总分排序
//比较语文成绩
int num2 = num == 0 ? s1.getChinese() - s2.getChinese() :num;
//比较数学成绩
int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
//比较英语成绩
int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() :num3;
// 当其他相同时比计较姓名内容是否相同
int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName())
: num4;
return num5;
}
});
System.out.println("请输入成绩:");
for (int x = 1; x <= 5; x++) {
// 创建键盘录入对象
// 为了方便录入数据,数据类型都使用String类型接收
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + x + "个学生的姓名:");
String name =sc.nextLine();
System.out.println("请输入第" + x + "个学生的语文成绩:");
String chineseString = sc.nextLine();
System.out.println("请输入第" + x + "个学生的数学成绩:");
String mathString = sc.nextLine();
System.out.println("请输入第" + x + "个学生的英语成绩:");
String englishString = sc.nextLine();
Student s = new Student();
s.setName(name);
s.setChinese(Integer.parseInt(chineseString));
s.setMath(Integer.parseInt(mathString));
s.setEnglish(Integer.parseInt(englishString));
ts.add(s);
}
System.out.println("成绩录入结束:");
System.out.println("学生成绩如下:");
System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩");
// 增强for遍历集合
for (Student s : ts) {
System.out.println(s.getName() + "\t" + s.getChinese() + "\t"
+ s.getMath() + "\t" + s.getEnglish());
}
}
}
输出结果
姓名 语文成绩 数学成绩 英语成绩
吴文龙 100 100 100
杨启龙 99 100 100
邓聪 99 100 100
彭楷 100 99 99
杨晓洲 98 100 99