Set接口没有提供Collection接口额外的方法,但实现Set接口的集合类中的元素是不可重复的。
总结: 无序不可重复
实现原理:
实现Set接口的集合存储对象时: 1、 根据每个对象的哈希码值(调用hashCode()获得)用固定的算法算出它的存储索引,把对象存放在一个叫散列表的相应位置(表元)中: a存对象时,集合首先调用该对象的hashCode方法来获得该对象的hashCode值,与hash表中的值进行比较。如果不存在,则根据直接把该对象存入集合中,并把该hashCode值存入hash表中,此次add操作结束。如果存在,则进行下面的计算。
b通过”==”操作符判断已经存入的对象与要存入的对象是否为同一对象。如果true则集合认为添加相同对象,add失败。如果false(不是同一对象),则进行下面的计算。
c调用要添加的对象的equals()方法,并把集合中的另一元素作为参数传入,如果返回值为true则集合认为添加相同对象,add失败。否则添加成功。
2、 取对象时:根据对象的哈希码值计算出它的存储索引,在散列表的相应位置(表元)上的元素间进行少量的比较操作就可以找出它。
3、 Set接口存、取、删对象都有很高的效率。 对于要存放到Set集合中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法以实现对象相等规则。
public class Demo { public static void main(String[] args) { // 创建一个HashSet对象,set没有下标 Set<String> set = new HashSet<>(); set.add("a"); set.add("c"); set.add("d"); set.add("b"); Iterator<String> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }重写HashCode和equals方法:
因为hashCode()和equals()方法的返回值共同决定了两个对象是否相等,所以覆写着两个方法时一般要保证两个方法的返回值保证兼容。
重写hashCode()和equals()方法的基本规则: 1、 如果两个对象通过equals()方法比较时返回true,则两个对象的hashCode()方法返回值应该也相等。
2、 对象中用作equals()比较标准的成员变量(属性),也应该参与到hashCode的计算
引用数据类型
User.java
public class User implements Comparable<User> { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(String name) { super(); this.name = name; } public User(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { return age + name.hashCode(); } @Override public boolean equals(Object obj) { if (obj == null && !(obj instanceof User)) { return false; } User user = (User) obj; return name.equals(user.name) && age == user.getAge(); } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } // 比较大小的方法 /* * 返回值是int类型 * this和other比 * 返回值>0 this>other 在集合中代表在后面 * 返回值<0 this<other * 返回值=0 this==other */ @Override public int compareTo(User other) { /*if(this.age > other.age){ return 1; }else if(this.age < other.age){ return -1; } return 0;*/ // return this.age - other.age; if(this.age==other.age){ //年龄相等再比小明 return this.name.compareTo(other.name); }else{ return this.age - other.age; } } }Demo2.java
public class Demo2 { public static void main(String[] args) { Set<User> users = new HashSet<>(); User user1 = new User("小明", 4); User user2 = new User("小黄", 5); User user3 = new User("小黑", 6); User user4 = new User("小明", 4); users.add(user1); users.add(user2); users.add(user3); users.add(user4); for (User user : users) { System.out.println(user); } } }底层用链表记录了HashSet元素的插入顺序
Demo3.java
还是上面的User
//删除重复元素 public class Demo3 { public static void main(String[] args) { List<User> list = new ArrayList<>(); User user1 = new User("小明", 4); User user2 = new User("小黄", 5); User user3 = new User("小黑", 6); User user4 = new User("小明", 4); User user5 = new User("小黑", 6); list.add(user1); list.add(user2); list.add(user1); list.add(user2); list.add(user3); list.add(user4); list.add(user2); list.add(user3); list.add(user4); list.add(user2); list.add(user3); list.add(user5); /*for (int i = 0; i < list.size(); i++) { User user = list.get(i); for (int j = i + 1; j < list.size(); j++) { if (user.equals(list.get(j))) { list.remove(j); j--; } } } for (User user : list) { System.out.println(user); }*/ //无序 /*HashSet<User> set = new HashSet<>(); set.addAll(list);*/ //能记住顺序 LinkedHashSet<User>set=new LinkedHashSet<User>(); set.addAll(list); list.clear(); list.addAll(set); for (User user : list) { System.out.println(user); } } }总结:一个有序的HashSet
//对list集合中的元素进行排序 public class Demo4 { public static void main(String[] args) { extracted(); extracted2(); } private static void extracted2() { List<User> users = new ArrayList<>(); // 按照user的年龄升序排序 User user1 = new User("小黄", 5); User user2 = new User("小黑", 6); User user3 = new User("小明", 4); User user4 = new User("小绿", 4); users.add(user1); users.add(user2); users.add(user3); users.add(user4); for (int i = 0; i < users.size() - 1; i++) { for (int j = 0; j < users.size() - 1 - i; j++) { User a = users.get(j); User b = users.get(j + 1); if (a.compareTo(b) > 0) { users.set(j, b); users.set(j + 1, a); } } } for (User user : users) { System.out.println(user); } } private static void extracted() { List<Integer> list = new ArrayList<>(); list.add(5); list.add(4); list.add(7); list.add(3); list.add(1); list.add(2); for (int i = 0; i < list.size() - 1; i++) { for (int j = 0; j < list.size() - 1 - i; j++) { int a = list.get(j); int b = list.get(j + 1); if (a > b) { list.set(j, b); list.set(j + 1, a); } } } for (Integer integer : list) { System.out.println(integer); } } }User中实现了用于比较的compareTo()方法
