1.TreeSet集合
本质基于TreeMap的底层实现(红黑树结构---->自平衡"的二叉树结构")
有两种排序方式:
自然排序
选择器排序
什么时候使用者两种排序:
取决于创建当前Set集合对象的时候的构造方法
public TreeSet():默认的自然顺序排序
TreeSet<Integer>
由于TreeSet属于Set集合(本身保证元素唯一,不重复的元素!),所以可以将元素按照自然顺序排序
代码体现
public class TreeSetDemo {
public static void main(String[] args) {
//创建一个TreeSet集合对象
//public TreeSet():默认的自然顺序排序
TreeSet<Integer> ts = new TreeSet<Integer>(); //无参构造方法:自然排序
//添加元素
ts.add(20) ;
ts.add(17) ;
ts.add(24) ;
ts.add(18) ;
ts.add(17) ;
ts.add(23) ;
ts.add(24) ;
//遍历这个集合
for(Integer i : ts) {
System.out.print(i+" ");
}
}
}
/*
输出结果为: 17 18 20 23 24
*/
有参构造
代码体现
/*
* 使用TreeSet集合存储自定义对象并遍历
* 主要条件: 学生年龄的从小到大排序
* 使用比较器排序完成
* TreeSet集合有参构造方法
* public TreeSet(Comparator<? super E> comparator)
*
* */
public class TreeSetDemo {
public static void main(String[] args) {
//public TreeSet(Comparator<? super E> comparator)
//创建TreeSet集合
//方式1:直接给了创建了接口子实现类
//TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
//形式参数是一个接口类型,需要传递该接口子实现类对象
//方式2:形参参数如果接口:传入接口的匿名内部类(本质:接口的子实现类)
//匿名内部类(推荐的方式)
/*
* 匿名内部类的格式:
* new 类名/接口名(){
* 重写抽象类中或者接口中的抽象方法...
* };
* */
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//主要条件: 学生年龄的从大到小排序
//s1---->this
//s2---->s
int num = s2.getAge() - s1.getAge() ;
//学生年龄相同,比较姓名是否一样
int num2 = (num==0) ? (s1.getName().compareTo(s2.getName())): num ;
return num2;
}
}) ;
//添加元素
Student s1 = new Student("gaoyuanyuan",41) ;
Student s2 = new Student("gaoyuanyuan",41) ;
Student s3 = new Student("dengchao",37) ;
Student s4 = new Student("zhangyio",37) ;
Student s5 = new Student("wuqilong",50) ;
Student s6 = new Student("zhangguorong",20) ;
Student s7 = new Student("bybyzsd",29) ;
//添加集合中
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
//遍历
for(Student s: ts) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
// 学生类
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;
}
//重写toSttring方法
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
2.Map集合
java.util.Map<K,V>:接口
Map集合的功能
Map集合的功能:
添加功能
V put(K key, V value) :添加一个键值对元素
问题:返回值是什么意思
/如果当前键是一次存储的时候,返回的结果null
//如果键是不是第一次存储,后面重复,将当前对应的值把以前的值覆盖掉并保存下来,返回以前的值!
刪除功能:
V remove(Object key):刪除指定的键,返回的是跟键关联的值,如果没有映射关系,则返回null
void clear():删除全部的键以及值
判断功能
boolean containsKey(Object key):是否包含指定的键
boolean containsValue(Object value):是否包含指定的值
boolean isEmpty():判断Map集合是否为空
Map集合功能的代码体现
public class MapDemo {
public static void main(String[] args) {
//Map集合不能直接实例化
//HashMap:哈希表结构:保证元素(键:唯一),不能保证迭代顺序恒久不变
Map<String,String> map = new HashMap<String,String>() ;
//System.out.println(map);
//V put(K key, V value) :添加一个键值对元素
//System.out.println(map.put("杨过", "小龙女")) ;
/*
map.put("杨过", "小龙女") ;
map.put("胡歌", "王晓晨") ;
map.put("陈玄风", "梅超风") ;
map.put("赵又廷", "高圆圆") ;
*/
//如果当前键是一次存储的时候,返回的结果null
//如果键是不是第一次存储,后面重复,将当前对应的值把以前的值覆盖掉并保存下来,返回以前的值!
System.out.println(map.put("文章", "马伊琍")) ;
System.out.println(map.put("文章", "姚笛"));
System.out.println(map);
System.out.println("---------------------");
//V remove(Object key)
//System.out.println(map.remove("杨过"));
//void clear():删除全部的键以及值
//map.clear();
//boolean containsKey(Object key):是否包含指定的键
//boolean containsValue(Object value):是否包含指定的值
System.out.println(map.containsKey("黄晓明"));
System.out.println(map.containsKey("赵又廷"));
System.out.println(map.isEmpty());
System.out.println(map);
}
}
Map集合的高级功能
高级功能:
方式1:(推荐的方式:Map常用的方式)
Set<K> keySet():获取所有的键的集合
V get(Object key):通过键获取对应的值
编译方式一:
public class MapDemo2 {
public static void main(String[] args) {
//创建Map集合对象
Map<String,String> map = new HashMap<String,String>() ;
//添加键值对元素
map.put("郭靖", "黄蓉") ;
map.put("杨过", "小龙女") ;
map.put("令狐冲", "任盈盈") ;
map.put("陈玄风", "梅超风") ;
//遍历Map集合
//方式1:Set<K> keySet():获取所有的键的集合
Set<String> set = map.keySet() ;
//通过键在值
for(String key : set) {
//通过键获取值
// V get(Object key):通过键获取对应的值
String value = map.get(key) ;
System.out.println(key+"="+value);
}
}
}
遍历方式二:
/*
* 方式2遍历
* Set<Map.Entry<K,V>> entrySet():获取当前Map集合中所有的键值对对象
*
* K getKey() :通过键值对对象获取键
* V getValue():通过键值对对象获取值
*
* */
public class MapDemo3 {
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<String,String>() ;
//添加元素
map.put("郭靖", "黄蓉") ;
map.put("杨过", "小龙女") ;
map.put("令狐冲", "任盈盈") ;
map.put("陈玄风", "梅超风") ;
//方式2:
//获取所有的键值对对象
Set<Map.Entry<String, String>> entrySet = map.entrySet() ;
//遍历
for(Map.Entry<String, String> entry :entrySet) {
//获取到了所有的键值对对象:一一获取
//K getKey():通过键值对对象获取键
String key = entry.getKey() ;
//V Value():通过键值对对象获取值
String value = entry.getValue() ;
System.out.println(key+"="+value);
}
}
}
HashMap<K,V>
HashMap<K,V>是Map集合的子实现类,里面哈希表结构,保证(键唯一)
/*
*
* Map集合只只针对键有效
* HashMap<Integer,String>键:Integer
*
* HashMap<String,Student> :键:String
* HashMap<Student,String>:键是自定义对象
*
*
*
*
* 对于Map存储的键如果是自定义对象:该自定义对象的所在类必须重写Object:equals()和hashCode()
* 会依赖于HashMap的put方法
* hash()---->依赖于hashCode():算出每一个对象哈希码值一样
* putValue()---->equals()方法:哈希码值一样,还有比较每一个成员信息是否相同!
* */
public class HashMapDemo {
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<Integer,String> hm = new HashMap<Integer,String>() ;
//添加元素
hm.put(1, "马云") ;
hm.put(2, "雷军") ;
hm.put(3, "罗永浩") ;
hm.put(4, "刘强东") ;
hm.put(5, "裘博君") ;
hm.put(1, "李嘉城") ;
//遍历
//获取所有的键
Set<Integer> set = hm.keySet() ;
for(Integer key :set) {
//通过键获取值
String value = hm.get(key) ;
System.out.println(key+"----"+value);
}
}
}
/*
输入结果为:
1----李嘉城
2----雷军
3----罗永浩
4----刘强东
5----裘博君
*/
Collections类
/**
* Collections:java.util.Collections 类
* 可以针对Collection集合进行操作的工具类!
*
* public static <T> int binarySearch(List<?> list,T key):针对集合的二分查询方法:
* 查询key在集合中出现的索引值
* public static <T> T max(Collection<? extends T> list):获取集合中最大值
* public static <T> T min(Collection<? extends T> list):获取集合中最小值
* public static <T> void sort(List<T> list):针对List集合进行排序:升序排序
* public static <T> void sort(List<T> list,Comparator<T> com):比较器排序
* public static void shuffle(List<?> list):针对List集合的元素进行随机置换
*
* @author zhangyang
*
*/
public class CollectionsDemo {
public static void main(String[] args) {
//创建List集合对象
List<Integer> list = new ArrayList<Integer>() ;
//添加元素
list.add(10) ;
list.add(20) ;
list.add(50) ;
list.add(25) ;
list.add(5) ;
list.add(15) ;
list.add(75) ;
System.out.println(list);
System.out.println("---------------------------------");
//public static <T> void sort(List<T> list):针对List集合进行排序:升序排序
Collections.sort(list);
System.out.println(list);
//public static <T> int binarySearch(List<?> list,T key)
//二分搜索法:集合:必须是有序的!:查询25这个元素在有序集合出现的索引值
System.out.println("binartSeach():"
+Collections.binarySearch(list, 25));
System.out.println("----------------------------------");
// public static <T> T max(Collection<? extends T> list)
System.out.println("max():"+Collections.max(list));
System.out.println("----------------------------------");
//public static void shuffle(List<?> list):
Collections.shuffle(list);
System.out.println(list);
}
}
3.多线程
线程和进程的概念
什么是线程,
线程是依赖于进程的,将线程看成是进程中某个"任务"
什么是进程:
本地开启一个客户端,就是一个进程 "任务管理器"!
能够调用系统资源的独立单位
多进程的意义?
多进程的意义:就是为了提高cpu的使用率!
举例:
现在大部分计算机都是多进程的计算机!
打游戏的同时,可以听音乐.. 这两个进程是同时的吗?
这两个进程不是同时进行的,它是在两个进程之前抢占cpu的时间片!
(两个进程之间高效的来回切换...)
线程
线程---->理解为 进程的中的任务
举例:
360软件
开启360----开启一个进程
杀毒的同时可以清理内存...
迅雷下载电视剧:30集
多线程的意义呢?
每个线程为了抢占CPU的执行权,他们的抢占过程中具有随机性!
举例
1 v 5打篮球
5个人抢占篮球的几率大,但是一定抢占到吗?
不一定能够一直能抢占到! 线程的执行具有随机性!
jvm:是假想计算机---开启对应进程
jvm:里面至少有两条线程
main方法: 主线程----"用户线程"
垃圾回收线程:产生很多对象的时候,需要通过gc回收没有更多引用的对象!
public staic void main(String[] args){
new Object() ;
new Object() ;
....
FileInputStream fis = new FileInputStream("d:\\a.txt") ;
}
线程的几种状态
State:线程的状态:是Thread类内部枚举
public enum State {
NEW, 线程新建状态 ---->public static final...
RUNNABLE,线程运行状态
BLOCKED,线程阻塞状态(sleep(),等待)
WAITING,//死死等待
TIMED_WAITING,//超时等待 等待到一定时间,不等了
TERMINATED;//线程终止!
}
多线程实现方式一和实现方式二的对比:
方式1:
1)自定义一个类MyThread,继承自 Thread
2)重写Thread类中run方法
3)在main中,创建该线程类对象
MyThread my1 = new MyThread() ;
MyThread my2 = new MyThread() ;
MyThread my3 = new MyThread() ;
my1.start();
my2.start() ;
my3.start() ;
my1,my2在并发的执行
继承关系的弊端:
局限性
它不能够体现出"数据共享"的概念!
电影卖票:100张票 三个窗口
每一个窗口可能都在卖自己的100张票
线程的执行 "随机性"
原子性操作:
100张: 变量tickets (tickets--) 100 --- 99
栈内存 堆内存
MyThread my1 new MyThread() ;
MyThread my2 new MyThread() ;
MyThread my3 new MyThread() ;
第二种方式
优势:静态代理
能够体现出 "资源共享"
1)自定义一类MyRunnable implements Runnable
2)重写run方法
3)创建资源类对象,创建线程类对象,将资源类对象当做参数传递
MyRunnable my = new MyRunnable() ;
// public Thread(Runnable target, String name) :创建线程类对象并同时给线程设置名称
Thread t1 = new Thread(my, "窗口1") ;
Thread t2 = new Thread(my, "窗口2") ;
Thread t3 = new Thread(my, "窗口3") ;
//启动线程
t1.start();
t2.start();
t3.start();
栈内存中 堆内存中
Thread t1 new Thread(0x01) Thread(Runnable runable)
Thread t2 ....
Thread t3 ...
MyRunnable my(0x01) ------> new MyRunnable()