文章 | 链接 |
---|---|
Java语法 | https://blog.csdn.net/weixin_45606067/article/details/107049186 |
一维数组与二维数组、内存解析 | https://blog.csdn.net/weixin_45606067/article/details/107049178 |
面向对象(1/3)类和对象 | https://blog.csdn.net/weixin_45606067/article/details/108234276 |
面向对象(2/3)封装性、继承性、多态性 | https://blog.csdn.net/weixin_45606067/article/details/108234328 |
面向对象(3/3)抽象类、接口、内部类、代码块 | https://blog.csdn.net/weixin_45606067/article/details/108258152 |
异常处理 | 待更新 |
多线程(1/2) | https://blog.csdn.net/weixin_45606067/article/details/107067785 |
多线程(2/2) | https://blog.csdn.net/weixin_45606067/article/details/107067857 |
常用类 | https://blog.csdn.net/weixin_45606067/article/details/108283203 |
枚举与注解 | 待更新 |
集合(1/5)Collection、Iterator、增强for | https://blog.csdn.net/weixin_45606067/article/details/107046876 |
集合(2/5)List、ArrayList、LinkedList、Vector的底层源码 | https://blog.csdn.net/weixin_45606067/article/details/107069742 |
集合(3/5)set、HashSet、LinkedHashSet、TreeSet的底层源码 | |
集合(4/5)Map、HashMap底层原理分析 | https://blog.csdn.net/weixin_45606067/article/details/107042949 |
集合(5/5)LinkHashMap、TreeMap、Properties、Collections工具类 | https://blog.csdn.net/weixin_45606067/article/details/107069691 |
泛型与File | https://blog.csdn.net/weixin_45606067/article/details/107124099 |
IO流与网络编程 | https://blog.csdn.net/weixin_45606067/article/details/107143670 |
反射机制 | 待更新 |
Java8新特性 | https://blog.csdn.net/weixin_45606067/article/details/107280823 |
Java9/10/11新特性 | 待更新 |
1.Set接口的框架结构:存储无顺序的,不可重复的数据。
2.如何理解Set的无序,不可重复。
以HashSet为例说明:
①无序性:不等于随机性。
存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值添加。
②不可重复性:保证添加的元素按照equals()方法判断时,不能返回true。即,相同的元素只能添加一个。
3.Set接口中没有额外定义新的方法,使用的都是Collection接口中声明过的方法。
4.添加元素的过程:以HashSet为例:
我们像HashSet中添加元素a,首先调用元素a所在类的hashcode方法,计算a的哈希值,
此哈希值通过某种算法计算中在HashSet底层数组的存放位置(即:索引位置),
判断数组此位置是否已经有元素:
如果此位置上没有其他元素,则元素a直接添加成功。---情况1
如果此位置有其他元素b(或以链表形式存在多个元素),则比较a和b的哈希值:
如果哈希值不相同,则元素a添加成功。 ---情况2
如果哈希值相同,则调用元素a所在类的equals()方法:
equals()返回true,元素添加失败。
equals()返回返回false,则元素a添加成功。 ---情况3
说明:对于添加成功的情况2和情况3而言:元素a与已经存在指定位置上数据以链表方式存。
jdk7中:元素a放到数组中,指向原来的元素。
jdk8中原来的元素放在数组中,指向a元素。
5.要求:
①向Set中添加的数据,其所在的类一定要重写hashCode()和equals()方法
②重写hashCode()和equals()方法尽可能保持一致:相等的对象必须具有相等的哈希值。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
list.add("456");
List list2=duplicateList(list);
Iterator<String> iterator = list2.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next ());
}
}
public static List<String> duplicateList(List list){
HashSet<String> set = new HashSet<>();
set.addAll(list);
return new ArrayList(set);
}
添加元素的过程:以HashSet为例:
我们像HashSet中添加元素a,首先调用元素a所在类的hashcode方法,计算a的哈希值,
此哈希值通过某种算法计算中在HashSet底层数组的存放位置(即:索引位置),
判断数组此位置是否已经有元素:
如果此位置上没有其他元素,则元素a直接添加成功。---情况1
如果此位置有其他元素b(或以链表形式存在多个元素),则比较a和b的哈希值:
如果哈希值不相同,则元素a添加成功。 ---情况2
如果哈希值相同,则调用元素a所在类的equals()方法:
equals()返回true,元素添加失败。
equals()返回返回false,则元素a添加成功。 ---情况3
1.LinkedHashSet的使用:
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了一对双向链表,记录此数据的前一个数据和后一个数据。
2.优点:
对于频繁遍历的操作,LinkedHashSet的效率高于HashSet。
1.向TreeSet中添加的数据,要求是同一个类的对象,不能添加不同类的对象。
2.两种排序方式:自然排序(实现Comparable接口)和定制排序(实现Comparator接口)
3.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()
代码实现:
@Test
public void test1(){
TreeSet set = new TreeSet();
//举例1:
set.add(34);
set.add(-25);
set.add(77);
set.add(8);
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("*************举例2*****************");
TreeSet set1 = new TreeSet();
set1.add(new User("Tom",22));
set1.add(new User("Jerry",24));
set1.add(new User("BeiBei",21));
set1.add(new User("DongDong",20));
set1.add(new User("MM",53));
set1.add(new User("MM",18));
Iterator iterator1 = set1.iterator();
while (iterator1.hasNext()){
System.out.println(iterator1.next());
}
}
}
public class User implements Comparable{
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", 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) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//按照姓名从大到小排序,年龄从小到大排序,
@Override
public int compareTo(Object o) {
if (o instanceof User){
User user= (User) o;
int num= this.name.compareTo(user.name);
if (num!=0){
return -num;
}else{
return Integer.compare(this.age,user.age);
}
}else{
throw new RuntimeException("类型不一致!");
}
}
}
定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()。
代码实现:
@Test
public void test2(){
Comparator comparator = new Comparator(){
//按照年龄从小到大排序
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof User && o2 instanceof User){
User d1= (User) o1;
User d2= (User) o2;
return Integer.compare(d1.getAge(),d2.getAge());
}else{
throw new RuntimeException("类型不一致!");
}
}
};
TreeSet set = new TreeSet(comparator);
set.add(new User("Tom",22));
set.add(new User("Jerry",24));
set.add(new User("BeiBei",21));
set.add(new User("DongDong",20));
set.add(new User("Mary",18));
set.add(new User("MM",18));
Iterator<Object> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}