1,set集合的特点:
1.1,set集合添加的数据不可重复
public static void main(String[] args) { Set s = new HashSet(); s.add("b"); s.add("a"); s.add("c"); s.add("b"); System.out.println(s); }
通过上一行代码输出的结果为:
由此可以说明set集合里的数据不可重复。
但是若存放的数据为对象时:
public static void main(String [] args) { HashSet<Object> set =new HashSet<Object>(); set.add(new person("zs",12)); set.add(new person("ww",12)); set.add(new person("ls",12)); System.out.println(set.size()); set.add(new person("ww",12)); System.out.println(set.size()); }
运行此段代码的结果如图:
由此可以说明但我们在set集合添加属性值一样的对象时,因为地址同所以可以存放进去,那我们该怎么解决?我们尝试用list集合去重原理试一下。
package com.xzs.set; import java.util.HashSet; import java.util.Set; public class demo1 { public static void main(String [] args) { HashSet<Object> set =new HashSet<Object>(); set.add(new person("zs",12)); set.add(new person("ww",12)); set.add(new person("ls",12)); System.out.println(set.size()); set.add(new person("ww",12)); System.out.println(set.size()); } } class person{ 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; } public person(String name, int age) { super(); this.name = name; this.age = age; } public person() { super(); } @Override public String toString() { return "person [name=" + name + ", age=" + age + "]"; } @Override // public int hashCode() { // final int prime = 31; // int result = 1; // result = prime * result + age; // result = prime * result + ((name == null) ? 0 : name.hashCode()); // return result; // } // @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; person other = (person) 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; } }
以上代码运行结果是
同样集合的长度还是3和4由此说明set集合与list集合判定的底层逻辑就不同
package com.xzs.set; import java.util.HashSet; import java.util.Set; public class demo1 { public static void main(String [] args) { HashSet<Object> set =new HashSet<Object>(); set.add(new person("zs",12)); set.add(new person("ww",12)); set.add(new person("ls",12)); System.out.println(set.size()); set.add(new person("ww",12)); System.out.println(set.size()); } } class person{ 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; } public person(String name, int age) { super(); this.name = name; this.age = age; } public person() { super(); } @Override public String toString() { return "person [name=" + name + ", age=" + age + "]"; } @Override public int hashCode() { System.out.println("hashcode被调用了"); final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @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; person other = (person) 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; } }
同样是上一行代码,这时候运行的结果为
由此可以说明,set集合在判定数据是先通过hascode,并且在上类代码中当我们的hashcode被注释的时候equlas,也不会被调用,所以set集合的判定是否为重复数组的原理是:“先来通过hashcode判定,才会进入equals判定”
1.2 hashset无序 Treeset有序
要想判定set集合是否为有序的我们可以遍历他的元素即可
1.2.1set集合的遍历方法
1.为迭代器也就是图中的Iterator
2.增强for也就是foreach
public static void main(String[] args) { Set s = new HashSet(); s.add("a"); s.add("c"); s.add("b"); for (Object o : s) { System.out.println(o); } System.out.println("=============================="); Iterator it = s.iterator(); while (it.hasNext()) { System.out.println(it.next()); } }
结果为:
证明 string 类型是可以自动排序的
1.2.2Treeset自定义对象无法排序,hashSet因为是无序所以会无规则遍历
package com.xzs.set; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class demo1 { public static void main(String [] args) { TreeSet<Object> set =new TreeSet<Object>(); set.add(new person("zs",3,12)); set.add(new person("ww",6,92)); set.add(new person("ls",1,17)); System.out.println(set.size()); for (Object object : set) { System.out.println(object); } } } class person{ private String name; private int level; private int age; public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } 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 person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "person [name=" + name + ", level=" + level + ", age=" + age + "]"; } public person(String name, int level, int age) { super(); this.name = name; this.level = level; this.age = age; } public person() { super(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + level; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; person other = (person) obj; if (age != other.age) return false; if (level != other.level) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
结果为:会出现数据转化异常
1.2.3如何让Treeset集合进行排序(自然排序.比较器排序 )
package com.xzs.set; import java.util.HashSet; import java.util.Iterator; import java.util.Objects; import java.util.Set; import java.util.TreeSet; public class demo1 { public static void main(String[] args) { Set s = new TreeSet(); s.add(new Student("zs",17)); s.add(new Student("ls",19)); s.add(new Student("ww",18)); System.out.println("目前集合容器中的元素:"+s); } } class Student implements Comparable{ private String name; private int age; public Student(String name, int age) { 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; } @Override public boolean equals(Object o) { System.out.println("调用了equals方法。。。"); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && name.equals(student.name); } @Override public int hashCode() { System.out.println("调用了hashCode方法。。。"); return Objects.hash(name, age); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Object o) { Student student = (Student) o; return this.age - student.age; } }
结果为:
当然我们也可以用TreeSet构造器使用实现java.util.Comparator的匿名内部类
如
package com.xzs.set; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.Objects; import java.util.Set; import java.util.TreeSet; public class demo1 { public static void main(String[] args) { TreeSet s=new TreeSet(new Comparator() { public int compare(Object o1, Object o2) { System.out.println("调用了compare方法。。。"); Student s1 = (Student) o1; Student s2 = (Student) o2; if (s1.getAge()-s2.getAge() == 0) return s1.getName().compareTo(s2.getName()); return s1.getAge()-s2.getAge(); } }); s.add(new Student("zs",16)); s.add(new Student("ls",17)); s.add(new Student("zs",17)); s.add(new Student("ww",18)); System.out.println("目前集合容器中的元素:"+s); } } class Student { private String name; private int age; public Student(String name, int age) { 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; } @Override public boolean equals(Object o) { System.out.println("调用了equals方法。。。"); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && name.equals(student.name); } @Override public int hashCode() { System.out.println("调用了hashCode方法。。。"); return Objects.hash(name, age); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
得到的结果为: