1.set集合
特点:无序(没有下标) 不重复
子类: HashSet : 去重的功能; LinkedHashSet:表示的是有序的;
TreeSet: 有自己独特的方法:排序的功能
1.1关于HashSet去重的问题:
HashSet 在存放对象的时候会判断对象是不是同一个对象 .
1. 默认引用类型比较的是地址值,如果地址相同,name这是一模一样的对象,将不再重复往里面放.
2 . 如果对象 重写了hashcode和equals放法,就比较这两者是否相等.
如果hashcode相等,那么比较的是equals方法,如果equals再相等,那么证明这是同一个对象,如果equals不相等,
那么即使hashcode相等,也是两个对象.
3.HashSet已经重写了父类的equals和hashcode方法;
注意:equals和 == 区别!
简单的说,“==”用于判断引用是否相等,equals()用于判断值是否相等 public static void main(String[] args) { String a = new String("abc"); String b = new String("abc"); System.out.println(a==b);//结果为false System.out.println(a.equals(b));//结果为true }
例题:1. 创建一个HashSet 2. 保存 f f a a b b;(在系统类中操作去重)
只要创建对象,就会给没一个对象分配一个hashcode; hashcode 如果不同就不会调用equals .
HashSet<String>hash = new HashSet(); hash.add("f"); hash.add("f"); hash.add("a"); hash.add("a"); hash.add("b"); hash.add("b"); //迭代器遍历 Interator iterator=hash.iterator(); while(iterator.hasNext()){ String next = iterator.next(); System.out.println(next); //或者增强for 循环进行遍历 for (String string : hash){ System.out.println(string); } }
2 : HashSet如何在自己创建的类中去重
1. 自己创建一个Person类;创建一个集合保存6个Person;并且要去去重.
HashSet<Person> set = new HashSet<>(); set.add(new Person("张三"),12); set.add(new Person("张三"),12); set.add(new Person("张四"),13); set.add(new Person("张四"),13); set.add(new Person("张五"),14); set.add(new Person("张五"),14); //遍历集合 for(Person person:set){ System.out.println(set) } //想要获得的打印结果,需要重写Person的hashCode 和equals方法; Person [name=张三, age=12] Person [name=张四, age=13] Person [name=张五, age=14]
2.创建一个Person类;
public class Person implements Comparable<Person>{//这里实现comparable是为了下面用TreeSet排序; 在下面3中例题3里面有体现;
private String name ;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
//因为上面创建的集合要进行除重操作,这时父类的去重方法不再适用(父类==比较的是地址),我们需要重写hashCode和equals方法;
public int hashCode(){
//这里如果过返回值是一样的,默认两个对象是一样的;这里返回值我们和两个成员变量进行联系
return this.name.hashCode() + this.age;
}
//重写equals方法
public boolean equals (Object object){
Person p = (Person) object;
//如果字符串(name) 一样并且年龄的数值一样,那么这两个对象就是一样的这样我们就可以进去重了;
return this.name.equals(p.name)&&this.getAge==p.getAge()
}
}
public int compareTo(Person o) { //此处重写了接口compareble中的 compareTo方法;
// TODO Auto-generated method stub
//按照年龄排序,如果是int 直接相减;
//return (this.age) - (o.getAge());
//按照姓名比较需要使用字符串compare"To进行比较 返回int值点进去看;
//return this.name.compareTo(o.getName());
int num = this.age -o.getAge();
//这时啥意思;
return num==0?this.name.compareTo(o.getName()):num;
}
3.利用set集合 去除ArrayList集合的重复元素; ArraysList里面保存着 a a b b c c d d ;
ArrayList<String> list = new ArrayList(); list.add("a") list.add("a") list.add("b") list.add("b") list.add("c") list.add("c") //创建HashSet集合接收一下,顺便去重 HashSet<String> set = new HashSet(); set.addAll(list); //将list集合里面的元素全部放到set里面去 list.clear(); //清空list list.addAll(set); //再将处理好的数据放回到list 里面; //增强for循环;遍历 for(String string: list)
4.编写一个程序,获取10个 1 -20的随机数,要去随机数不能重复 1.创建一个set 2. 循环生成10个数 3. 添加到set中去;
HashSet<Integer> set = new Integer(); while(set.size()<10){ int rd = (int)(Math.random()*(20-1+1)+1); //循环往集合里面添加数据; set.add(rd);//这里系统自动装箱,可一直接传入int类型的数字; } //打印集合长度 System.out.println(Hash.size()); 打印这个集合; System.out.println(set);
3 TreeSet是如何进行排序的:
TreeSet支持两种排序方法:自然排序和定制排序。TreeSet默认采用自然排序。
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系.然后将集合元素按升序排列,这种方式就是自然排序。(比较的前提:两个对象的类型相同)。
1.主要有两种方式
方式1: 1. Object实现comparable接口,可以重写compareTo方法; 2. 实现接口中的compareTo()方法; 3. 编写你想要的排序规则;(自己创建的类)在类里面
方式2: 1. 系统类 : (comparator)比较器. 1 创建比较器, 在创建一个是实现接口的实现类,重写compare()方法再将
实现类创建的一个对象,放入到 new TreeSet( new 对象);
两种重写方法返回值都是 int 类型;
1 . 创建一个TreeSet集合添加几个数,查看是如何排序的;(Integer比较的是数值的大小)
TreeSet(Integer)set = new TreeSet(); set.add(6); set.add(3); set.add(3);
set.add(7);set.add(5); System.out.println(set);//打印结果 [3, 5, 6, 7] //去重并且排序了;
2. 例题: 创建一个TreeSet集合,集合中保存的是字符串,按照字符串的长度进行排序,(这里使用的是系统类;)
这里我们需要重写比较规则,需要创建一个比较器(comparator),然后找个实现比较器的类,最后在初始化TreeSet对象的时候
将该实现类传进去;
2 : 创建一个类实现(接口comparator)中的Compara()方法;
public class StringLengthImpl implements Comparator <String>{ //实现比较器中的方法; public int compare(String o1,String o2){ //如果两个字符串长度不一样.直接返length; //字符串长度进行对比;返回值length int length = o2.length- o1.length; //如果长度相等要比较每一位了; int num1= o2.compareT(o1); //用判断语句接收上面返回的结果 int rel = length==0?num1:length; //最终判断,就算相等也不能赋值0.0会默认去重; return rel == 0 ?1:rel } }
注意:比较规则:
//自己创建的类要实现是comparable接口,要重写抽象方法; public int compareTo() { } //返回0的时候:只有一个元素; //所以我们不能让他返回零 //返回正数的时候:打印数据 正序输出; //返回负数的时候;打印的数据 倒序输出; //TreeSet 二叉树 //比我小的数值放到我的左边(返回负数的情况); //比我大的数值放到我的右边(返回正数的情况); //如果你返回的是零就不存储,
//集合中保存字符串,按照字符串长度排序; //使用比较器来进行排序; //在比较器中写你的比较规则; //利用TreeSet的构造方法 直接将比较器的实现类传进去;
TreeSet<String > set = new TreeSet<>(new StringLengthImpl());//此处传入实现类;
set.add("wanglong");
set.add("kun");
set.add("huxin");
set.add("zhangjianhai");
System.out.println(set);//打印一下就知道有没有实现comparable接口
例题3: 添加五个人( Person )然后进行排序;
TreeSet<Person> set = new TreeSet<>(); set.add(new Person("张三",11)); set.add(new Person("张4", 12)); set.add(new Person("张5", 13)); set.add(new Person("张6", 14)); System.out.println((int)'张'); System.out.println((int)'三'); System.out.println(set);
例题4: 排序而且不用去重复(用比较器) 2. 主要按照字符串进行比较,次要按照字符进行比较;
首先: 使用比较器;
class StringLengthImpl implements Comparator<String> { // 实现比较器方法; @Override public int compare(String o1, String o2) { // 实现比较器规则长度比较; int length = o1.length() - o2.length(); // 字符串比较 int num1 = o1.compareTo(o2); int rel = length == 0 ? num1 : length; return rel == 0 ? 1 : rel; } }
private static void 排序2() { // 要求: 排序,而且还不能去除重复(用比较器) // 主要按字符串长度比较 次要按字符串字符比 ArrayList<String> set = new ArrayList<>(); set.add("wanglong"); set.add("wanglong"); set.add("kun"); set.add("huxin"); set.add("zhangjianhai"); //将接口传进去; TreeSet<String > set1 = new TreeSet<>(new StringLengthImpl()); set1.addAll(set); set.clear(); set.addAll(set1); System.out.println(set1); }
例题5: 键盘输入一个字符串,程序对其中所有的字符进行排序.要求保留重复的.
//char比较器 class CharLengthImp implements Comparator<Character>{ @Override public int compare(Character o1, Character o2) { int num = o1.compareTo(o2); //等于零不能删除,等于num判断正负 return num==0 ?1:num; } }
System.out.println("请输入一个字符串"); Scanner scanner = new Scanner(System.in); String string= scanner.nextLine(); //字符串转换成字符数组;toCharArray(); char[] array = string.toCharArray(); //创建排序的集合 TreeSet<Character> set = new TreeSet<>(new CharLengthImp()); //将字符数组中的字符添加到Set中; for (int i = 0; i < array.length; i++) { //将字符数组每一项穿进去; set.add(array[i]); } System.out.println(set);
例题6.程序启动后,可以接收多个整数,直到输入quit 时候结束输入,把所有输入的整数倒序排列;
class NumberCompare implements Comparator<Integer>{ @Override public int compare(Integer o1, Integer o2) { int num = o1-o2; //如果等于零返回1,否则返回num; return num ==0 ? 1 : num; //在构造中加入; } }
System.out.println("请输入整数 quit 时候结束;"); Scanner scanner = new Scanner(System.in); TreeSet<Integer> set = new TreeSet<>(new NumberCompare()); while (true) { // 接收用户输入; String string = scanner.nextLine(); // 判断是不是quit if (string.equals("quit")) { break; } // 转化成数字; int num = Integer.parseInt(string); // 保存到集合中排序; set.add(num); } System.out.println(set);
例题7:
/* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩) 录入的学生信息格式(姓名,语文成绩,数学成绩,英语成绩) 按照总分从高到低输出到控制台。输出学生所有信息*/ //创建set保存学生;
创建学生类:
public class Student implements Comparable<Student> { private String name; private int chinese; private int math; private int english; private int sum; public Student(String name, int chinese, int math, int english) { super(); this.name = name; this.chinese = chinese; this.math = math; this.english = english; this.sum = chinese + math + english; } @Override public String toString() { return "Student [name=" + name + ", chinese=" + chinese + ", math=" + math + ", english=" + english + ", sum=" + sum + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getChinese() { return chinese; } public void setChinese(int chinese) { this.chinese = chinese; } public int getMath() { return math; } public void setMath(int math) { this.math = math; } public int getEnglish() { return english; } public void setEnglish(int english) { this.english = english; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; } public Student() { super(); // TODO Auto-generated constructor stub } //在类中实现 @Override public int compareTo(Student o) { int num = this.sum-o.getSum(); return num==0?1:num; } }
private static void fun7键盘输入数字打印结果() { /* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩) 录入的学生信息格式(姓名,语文成绩,数学成绩,英语成绩) 按照总分从高到低输出到控制台。输出学生所有信息*/ //创建set保存学生; TreeSet<Student> set = new TreeSet<>(); Scanner scanner = new Scanner(System.in); //循环五次; while (set.size()<5) { System.out.println("请输入学生成绩按照格式姓名,语文成绩,数学成绩,英语成绩"); //接收用户输入 王龙,150,150,150; String string = scanner.nextLine(); //切割字符串; String[] strings = string.split(","); //从数组中取出数据 String name= strings[0]; int chinese = Integer.parseInt(strings[1]); int math = Integer.parseInt(strings[2]); int english = Integer.parseInt(strings[3]); //创建学生对象; Student student = new Student(name, chinese, math, english); //添加到Set中; set.add(student); } //遍历集合 for (Student student : set) { System.out.println(student); } }