java学习笔记之Set、HashSet、TreeSet、排序的比较次数

set


元素不可重复,无序

通过分析HashSet的add()方法源码得知,添加不重复元素的关键在于两个方法:(1)hashCode()方法;(2)equals()方法
如果添加的是引用类型,那么需要重写这两个方法,原因在于HashMap的put方法中是这两个方法进行判断的。

package com.mcq;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javafx.beans.binding.StringBinding;
public class SetDemo {
	public static void main(String[] args) {
		Set<String> set=new HashSet<String>();
		set.add("小明");
		set.add("小花");
		set.add("小丽");
		Iterator<String> iterator = set.iterator();
		while(iterator.hasNext()){
			String next=iterator.next();
			System.out.println(next);
		}
		System.out.println(set.contains("小明"));
		
		for(String str:set){
			System.out.println(str);
		}
	}
}

重写hashCode方法和equals方法:

//Student.java
package com.mcq;

public class Student {
	private String name;
	private int age;
	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;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return -1;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(!(obj instanceof Student)){
			return false;
		}
		else {
			Student student=(Student)obj;
			if(student.getAge()==this.getAge()&&student.name==this.getName()){
				return true;
			}
			return false;
		}
	}
}	

//SetDemo.java
package com.mcq;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javafx.beans.binding.StringBinding;
public class SetDemo {
	public static void main(String[] args) {
		Set<Student> set=new HashSet<Student>();
		set.add(new Student("小明",19));
		set.add(new Student("小强",20));
		set.add(new Student("小华",21));
		set.add(new Student("小强",20));
		for(Student student:set){
			System.out.println(student.getName()+" "+student.getAge());
		}
	}
}

 

增强for循环


语法:
for(数据类型 变量名:集合对象){
    语句体;
}
所有实现了Iterable接口的实现类都可以使用foreach语句
数组也可以用
foreach的数据类型可以是基本数据类型也可以是引用。

 

TreeSet


    1.元素不可重复
    2.可以按照自然顺序排序
    3.如果排序的是引用数据类型,需要实现Comparable接口
        此接口需要重写compareTo()方法,此方法规定:
        该对象小于、等于、大于指定对象,分别返回负数,0,正数。
    实例: 

方法一:实现接口Comparable

//Student.java

package com.mcq;
public class Student implements Comparable<Student>{
	private String name;
	private int age;
	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;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return -1;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(!(obj instanceof Student)){
			return false;
		}
		else {
			Student student=(Student)obj;
			if(student.getAge()==this.getAge()&&student.name==this.getName()){
				return true;
			}
			return false;
		}
	}
	public int compareTo(Student o) {
		// TODO Auto-generated method stub
		if(this.getAge()<o.getAge()){
			return -1;
		}else if(this.getAge()==o.getAge()){
			return 0;
		}else {
			return 1;
		}
	}
}	

//TreeSetDemo
package com.mcq;
public class Student implements Comparable<Student>{
	private String name;
	private int age;
	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;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return -1;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(!(obj instanceof Student)){
			return false;
		}
		else {
			Student student=(Student)obj;
			if(student.getAge()==this.getAge()&&student.name==this.getName()){
				return true;
			}
			return false;
		}
	}
	public int compareTo(Student o) {
		// TODO Auto-generated method stub
		if(this.getAge()<o.getAge()){
			return -1;
		}else if(this.getAge()==o.getAge()){
			return 0;
		}else {
			return 1;
		}
	}
}	

方法二:实现比较器Comparator

//MyComparator.java
package com.mcq;

import java.util.Comparator;

public class MyComparator implements Comparator<Student>{

	public int compare(Student o1, Student o2) {
		// TODO Auto-generated method stub
		if(o1.getAge()<o2.getAge()){
			return -1;
		}else if(o1.getAge()>o2.getAge()){
			return 1;
		}else {
			return 0;
		}
	}
	
}

//Student.java
package com.mcq;
public class Student{
	private String name;
	private int age;
	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;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return -1;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(!(obj instanceof Student)){
			return false;
		}
		else {
			Student student=(Student)obj;
			if(student.getAge()==this.getAge()&&student.name==this.getName()){
				return true;
			}
			return false;
		}
	}
//	public int compareTo(Student o) {
//		// TODO Auto-generated method stub
//		if(this.getAge()<o.getAge()){
//			return -1;
//		}else if(this.getAge()==o.getAge()){
//			return 0;
//		}else {
//			return 1;
//		}
//	}
}	

//TreeSetDemo.java
package com.mcq;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;
public class TreeSetDemo {
	public static void main(String[] args) {
		Set<Student> set=new TreeSet<Student>(new MyComparator());
		set.add(new Student("小明",18));
		set.add(new Student("小华",19));
		set.add(new Student("小丽",17));
		for(Student student:set){
			System.out.println(student.getName()+" "+student.getAge());
		}
	//	System.out.println("hello");
	}
}

方法三 :匿名内部类

package com.mcq;

import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;

public class TreeSetDemo {
	public static void main(String[] args) {
		Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
				return o1.getAge() - o2.getAge();
			}
		});
		set.add(new Student("小明", 18));
		set.add(new Student("小华", 19));
		set.add(new Student("小丽", 17));
		for (Student student : set) {
			System.out.println(student.getName() + " " + student.getAge());
		}
		// System.out.println("hello");
	}
}

更实用的排序方法:

package com.mcq;

import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;

public class TreeSetDemo {
	public static void main(String[] args) {
		Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
				int t=o1.getAge() - o2.getAge();
				return t==0?o1.getName().compareTo(o2.getName()):t;
			}
		});
		set.add(new Student("小明", 18));
		set.add(new Student("小华", 19));
		set.add(new Student("小丽", 17));
		for (Student student : set) {
			System.out.println(student.getName() + " " + student.getAge());
		}
		// System.out.println("hello");
	}
}

最后,自己之前一直不明白add的时候Comparator调用了几次,只想到了是个二叉排序树,其实TreeSet是个平衡二叉树,也就是说当二叉树不平衡时,会左旋或右旋(数据结构的基本知识)。举个栗子:

package com.mcq;

import java.util.Comparator;
import java.util.Set;
import java.util.HashSet;
import java.util.TreeSet;

public class TreeSetDemo {
	public static void main(String[] args) {
		Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
				System.out.println("compare...");
				System.out.println(o1+" "+o2);
				int t=o1.getAge() - o2.getAge();
				return t==0?o1.getName().compareTo(o2.getName()):t;
			}
		});
		set.add(new Student("1", 25));
		set.add(new Student("4", 21));
		set.add(new Student("2", 18));
		set.add(new Student("4", 21));
		set.add(new Student("3", 28));
//		for (Student student : set) {
//			System.out.println(student.getName() + " " + student.getAge());
//		}
		// System.out.println("hello");
	}
}

打印结果是:

compare...
4 21 1 25
compare...
2 18 1 25
compare...
2 18 4 21
compare...
4 21 4 21
compare...
3 28 4 21
compare...
3 28 1 25

我主要是第五个Compare我出了问题,开始把(1,25)作为根节点,当(2,18)插进去的时候(1,25)的左右深度相差就大于1了,这时,就要旋转了。旋转后,(4,21)就变成了根,再插(3,28)的时候就是先和(4,21)比较了,而不是我之前想的先和(1,26)比较。。至于我是怎么发现的呢?调试呀……set子目录下有个root变量,每次看root的变化就知道了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值