*Set集合
一个包含重复的元素collection,并且最多包含一个null元素,此类实现Set接口,有哈希表支持,Java中的预定义类型如String、Integer都可以在集合内使用;但对于自己创建的类型是,要注意到Set
需要一种方式来维护存储顺序,而存储顺序如何维护,则是在Set的不同实现间会有所变化。因此,不同的Set实现不仅具有不同的行为,而且他们对于可以在特定是我Set抓狂那个放置的元素类型也有不同要求
继承自Collection集合,哈希表通过它的自实现类HashSet集合实例化,HashSet集合底层是HashMap的实现
*List集合与Set集合的区别
List集合:元素是不唯一的,有序性(存储和取出是不一致的)
Set集合:元素是唯一的,存储和取出是不一致的
自定义存储对象没有重写 hashCode与equals方法,将无法保证元素的唯一性
package set; import java.util.HashSet; import java.util.Set; public class SetDemo { public static void main(String[] args) { //创建Set集合对象,Set集合是通过HashSet实现的 Set<String> set=new HashSet<String>(); //向集合中添加元素 set.add("hello"); set.add("hello"); set.add("JavaSE"); set.add("world"); set.add("world"); set.add("Java"); //增强for循环,遍历元素 for(String str : set){ System.out.println(str); } } }
*HashSet集合的add()方法,底层依赖于双列集合HashMap<K,V>的put(K key,V value)来实现的
put(K key,V value)底层是依赖于HashCod()和equals()
传递元素的时候,首先判断的是每一个元素对应的HashCode值是否一样,如果HashCode值一样,还要比较他们的equals()方法。由于现在集合存储的是String类型,String类型本身重写了equals()方法,所以默认比较的是内容是否相同,这里最终返回的就是第一次存储的那个元素,由此保证集合内元素的唯一性
(为快速查找而设计的Set,存入HashSet的元素必须定义hashCode())
package set; import java.io.Serializable; import java.util.HashSet; public class HashSetDemo1 implements Serializable{ private static final long serialVersionUID = 1L; transient int num ; public static void main(String[] args) { //创建集合对象 HashSet<String> hs=new HashSet<String>(); //向集合中添加元素 hs.add("hello"); hs.add("world"); hs.add("hello"); hs.add("JavaSe"); hs.add("Java"); hs.add("word"); hs.add("JavaWab"); //加强for循环,遍历集合 for(String str :hs){ System.out.println(str); } } }
//需求:存储自定义对象并遍历(使用HashSet集合)
HashSet<Student>()
package set; //自定义类 public class Student { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = 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; } } //测试类 package set; import java.util.HashSet; public class HashSetDemo { public static void main(String[] args){ //创建HashSet集合对象 HashSet<Student> hs=new HashSet<Student>(); //创建学生对象 Student st1=new Student("苹果",3); Student st2=new Student("梨",24); Student st3=new Student("桔子",15); Student st4=new Student("桔子",15); Student st5=new Student("桔子",17); Student st6=new Student("核桃",21); //向集合中添加元素 hs.add(st1); hs.add(st2); hs.add(st3); hs.add(st4); hs.add(st5); hs.add(st6); //增强for循环,遍历集合 for(Student st :hs){ System.out.println(st.getName()+"-----"+st.getAge()); } } }
*TreeSet(Set集合的重点)
(保持次序的Set,底层依赖于TreeMap实例,底层为红黑树结构,可以从Set中提取有序的序列)
*有两个构造方法(取决于开发者使用的是什么养的构造方法)
*public TreeSet():无参构造:根据其元素的自然顺序进行排序
package treeset; import java.util.TreeSet; public class TreeSetDemo { public static void main(String[] args) { //调用无参构造;元素将以自然排序进行排序 TreeSet<Integer> ts=new TreeSet<Integer>(); //向集合中添加元素 ts.add(67); ts.add(45); ts.add(64); ts.add(98); ts.add(23); //遍历元素 for(Integer in : ts){ System.out.print(in+" "); } } }
*publict TreeSet(Comparaptr<E> com)
*对于TreeSet集合要实现自然排序,那么该集合中存储的自定义类型必须实现Comparable接口, 并且必须重写该接口中的CompareTo()方法
*重写了Comparable接口中的CompareTo方法中代码需要自己给出(排序模式)
package treeset; //对于TreeSet集合存储自定义对象必须实现一个接口:compareable接口 public class Student implements Comparable<Student> { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = 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; } public int compareTo(Student st) { //排序的代码了,需要定义排序的条件 //主要条件:按照学生的年龄从小到大进行排序 int num =st.age - this.age ;//年龄从大到小 //比较完主要条件,还要还要比较次要条件:姓名内容也需要相同 int num2 = num==0 ? this.name.compareTo(st.name): num ; return num2 ; } } package treeset; import java.util.TreeSet; public class TreeSetDemo1 { public static void main(String[] args){ //创建对象 TreeSet<Student> ts=new TreeSet<Student>(); //创建Student对象 Student st1=new Student("山鬼谣",24); Student st2=new Student("山鬼谣",25); Student st3=new Student("弋痕夕",24); Student st4=new Student("山鬼谣",24); Student st5=new Student("千钧",15); Student st6=new Student("千钧",17); Student st7=new Student("辰月",16); //向集合中添加元素 ts.add(st1); ts.add(st2); ts.add(st3); ts.add(st4); ts.add(st5); ts.add(st6); ts.add(st7); //遍历元素,按年龄降序排列 for(Student st : ts){ System.out.println(st.getName()+"----"+st.getAge()); } } }
//键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
package treeset; public class Student1 { private String name; private int chineseScore; private int englishScore; private int mathScore; public Student1() { super(); } public Student1(String name, int chineseScore, int englishScore, int mathScore) { super(); this.name = name; this.chineseScore = chineseScore; this.englishScore = englishScore; this.mathScore = mathScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getChineseScore() { return chineseScore; } public void setChineseScore(int chineseScore) { this.chineseScore = chineseScore; } public int getEnglishScore() { return englishScore; } public void setEnglishScore(int englishScore) { this.englishScore = englishScore; } public int getMathScore() { return mathScore; } public void setMathScore(int mathScore) { this.mathScore = mathScore; } public int getSum(){ return this.chineseScore+this.englishScore+this.mathScore; } } package treeset; import java.util.Comparator; import java.util.Scanner; import java.util.TreeSet; public class TreeSetDemo2 { public static void main(String[] args) { // 创建TreeSet集合对象,使用有参构造 // 比较器排序匿名内部类的方式 TreeSet<Student1> ts = new TreeSet<Student1>(new Comparator<Student1>() { public int compare(Student1 st1, Student1 st2) { // 主要条件:总分从高到到第进行排序 int num = st2.getSum() - st1.getSum(); // 总分相同,不一定语文成绩相同,比较语文成绩 int num2 = num == 0 ? st1.getChineseScore() - st2.getChineseScore() : num; // 总分相同,语文成绩相同,比较数学成绩 int num3 = num2 == 0 ? st1.getEnglishScore() - st2.getEnglishScore() : num2; // 总分相同,语文成绩相同,数学相同,比较英语 int num4 = num3 == 0 ? st1.getMathScore() - st2.getMathScore() : num3; // 总分以及各科成绩都相同,不一定是同一个人,姓名内容是否相同 int num5 = num4 == 0 ? st1.getName().compareTo(st2.getName()): num4; return num5; } }); System.out.println("录入学生信息开始:"); // 键盘录入5个学生的信息,姓名,语文成绩,数学成绩,英语成绩 for (int i=1;i<=5;i++) { // 创建键盘录入对象 // 为了方便录入数据,数据类型都使用String类型接收 Scanner sc = new Scanner(System.in); System.out.println("请输入第"+i+"个学生的姓名:"); String name = sc.nextLine(); System.out.println("请输入第" +i+ "个学生的语文成绩:"); String chineseStr = sc.nextLine(); System.out.println("请输入第" +i+ "个学生的英语成绩:"); String mathStr = sc.nextLine(); System.out.println("请输入第" +i+ "个学生的数学成绩:"); String englishStr = sc.nextLine(); // 创建一个学生对象,把这些信息封装到学生对象中 Student1 st = new Student1(); st.setName(name); st.setChineseScore(Integer.parseInt(chineseStr)); st.setEnglishScore(Integer.parseInt(mathStr)); st.setMathScore(Integer.parseInt(englishStr)); // 将学生对象添加到集合中 ts.add(st); } System.out.println("学生信息录入结束:"); System.out.println("学生信息总分从高到底排列如下:"); //\t是制表符 System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩"); // 增强for遍历集合 for (Student1 std : ts) { System.out.println(std.getName() + "\t" + std.getChineseScore() + "\t" + std.getEnglishScore() + "\t" + std.getMathScore()); } } }
*对自定义对象什么情况下保证元素是唯一的
成员变量相同,认为是同一个元素
主要条件给定,需要分析次要条件
*使用比较器排序,使用匿名内部类
使用有参构造创建TreeSet集合对象
*LinkedHashSet<E>
具有可预知顺序的Set接口的哈希表链表实现
*由哈希保证元素的唯一性,有链接列表保证元素的有序性
package linkedhashset; import java.util.LinkedHashSet; public class LinkedHashSetDemo { public static void main(String[] args) { //创建LinkedHashSet集合对象 LinkedHashSet<String> link = new LinkedHashSet<String>(); //给集合中添加元素 link.add("hello") ; link.add("hello") ; link.add("world") ; link.add("Java") ; link.add("JavaSE") ; link.add("world") ; //增强 for循环,遍历集合 for(String s: link){ System.out.println(s); } } }