集合
- java的集合就像容器一样,是用来存储java类的对象,功能多,方便查找,存入,取出。
- 集合里面一般只能保存对象,就是保存对象的引用的变量,
Collection接口
1.List 有序,可重复
ArrayList:
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
LinkedList:
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
Vector:
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低
2.Set 无序,唯一
(1)HashSet:
底层数据结构是哈希表。(无序,唯一)
保证元素唯一性可以依赖两个方法:hashCode()和equals()
HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
具体实现唯一性的比较过程:
1.存储元素时首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,肯定是不同的对象。
2.hashCode值相同,再比较equals方法。
3.equals相同,对象相同。(则无需储存)
(2)LinkedHashSet:
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
3.Map接口:
Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。
Map接口有四个比较重要的实现类,分别是HashMap、LinkedHashMap、TreeMap和HashTable。
最主要的区别。
TreeMap是有序的,HashMap和HashTable是无序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。
HashMap
Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许重复,但允许值重复。
HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;
HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
HashMap基于哈希表结构实现的 ,当一个对象被当作键时,必须重写hasCode和equals方法。
LinkedHashMap
LinkedHashMap继承自HashMap,它主要是用链表实现来扩展HashMap类,HashMap中条目是没有顺序的,但是在LinkedHashMap中元素既可以按照它们插入图的顺序排序,也可以按它们最后一次被访问的顺序排序。
TreeMap
TreeMap基于红黑树数据结构的实现,键值可以使用Comparable或Comparator接口来排序。TreeMap继承自AbstractMap,同时实现了接口NavigableMap,而接口NavigableMap则继承自SortedMap。SortedMap是Map的子接口,使用它可以确保图中的条目是排好序的。
在实际使用中,如果更新图时不需要保持图中元素的顺序,就使用HashMap,如果需要保持图中元素的插入顺序或者访问顺序,就使用LinkedHashMap,如果需要使图按照键值排序,就使用TreeMap。
Hashtable
Hashtable和前面介绍的HashMap很类似,它也是一个散列表,存储的内容是键值对映射,不同之处在于,Hashtable是继承自Dictionary的,Hashtable中的函数都是同步的,这意味着它也是线程安全的,另外,Hashtable中key和value都不可以为null。
Object类
传递任何类型的类来使用
显示继承:
public class A extends Object{
}
隐式继承:就是不把extends Object 写出来
方法:
projected Object clone()/** 创建并且返回一个对象的拷贝**/
boolean equals(Object obj) /** 比较两个对象是否相等,用来比较两个引用的虚地址。当且仅当两个引用在物理上是同一个对象时,返回值为true,否则将返回false。**/
protected void finalize() /** 垃圾回收器确定不存在对该对象有更多的有引用的时候,会使用该方法**/
Class<?>getClass()/**获取该对象运行时候的类**/
int hashCode() /**获取对象的hash值**/
void notify() /**唤醒该对象上等待某个线程**/notifyAll则是/**等待的所有线程
String toString /**返回对象的字符串表示形式**/
void wait() /**让当前线程进入等待状态**?/
java序列化
就是把你得到对象拿出来,要把它封装起来。可以方便可以在网络上传输。
要想序列化成功要满足两个条件
该类必须实现 java.io.Serializable 接口。
该类的所有属性必须是可序列化的。
主要的类
//在项目中,服务端和客户端交互时,获取客户端传过来的信息时用这个会更好,否则可能会存在数据乱序的问题
序列化 ObjectOutputStream负责将对象写入字节流。
ObjectInputStream objectInputStream = new ObjectInputStream(clientSocket.getInputStream());
反序列化 ObjectInputStream从字节流重构对象。就是把对象从数据源还原回来
User userInformation=(User)objectInputStream.readObject();
多线程
多任务:
**理解:**人在吃饭时又玩手机,同时进行
多线程:
**理解:**打游戏时,它可以使多人一起打,多人相互独立不影响的去执行同一件事情。主路和子路,各走各的同时进行相互不影响,效率高
程序.进程(process)
编写的代码,是一个静态的概念,把代码跑起来就是一个进程.
进程(process).线程(thread)
一个进程可以有多个线程
**理解:**就如看电视的时候,既可以听到电视的声音,也可以看到电视中的弹幕
一个进程里面至少要有一个线程,这样才有存在的意义,
进程是系统分配的,线程才是cpu和执行的单位
存在关系:
程序》进程》线程(多个,mian是主线程)
核心概念
- 线程是独立的执行路径
- 要是程序在运行的时候没有创建线程的话,后台也会有多个线程在
- 有多个线程的话,运行的由调度器安排,不能人为去控制
- main()是主线程,是系统的入口,执行与整个程序
- 同一份资源操作,会有存在资源抢夺问题,需要加入并发控制。(比如买票时,人数大于票数的,就会加入并发进行排队,而不能同时)
线程的创建
java 提供了三种创建线程的方法:
- 通过实现 Runnable 接口;
- 通过继承 Thread 类本身;(可以实现Runnable接口)
- 通过 Callable 和 Future 创建线程。
Thread类
创建一个新的执行线程的方法:
1.将类声明为Thread类的子类,然后这个子类应该重写run类的方法Thread,然后分配启动子类的实例
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
自定义线程类继承Thread类
重写run方法,编写线程实体
创建线程对象,调用start方法启动线程(每次执行的输出都不一样,因为是由cpu进行调度的)
public class Test extends Thread{
@Override
public void run() {
//run方法线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码");
}
}
public static void main(String[] args) {
//main主线程
//创建线程对象
Test test=new Test();
test.start();
//main主线程
for (int j = 0; j < 20; j++) {
System.out.println("我在学习线程");
}
}
}
Runnable接口
推荐使用Runnable接口,这样还是使用其他接口
2.声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动。
lass PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
定义MyRunnable类是实现Runnable接口
实现run方法,编写线程的执行体
创建线程对象,然后调用start方法启动线程
test1 test = new test1();
new Thread(test).start();
public class test1 implements Runnable {
@Override
public void run() {
//run方法线程
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码");
}
}
public static void main(String[] args) {
//main主线程
//创建线程对象
test1 test = new test1();
new Thread(test).start();
//main主线程
for (int j = 0; j < 20; j++) {
System.out.println("我在学习线程");
}
}
}
区别
-
继承Thread类
子类去继承Thread类会具有多线程的能力,用子类对象:start()去启用线程,但是就会出现OOP单继承局限性
-
实现Ruunable
他也具有多线程能力,用传入目标对象+thread对象.start()去启用线程,他灵活方便,方便同一个对象被多给线程使用
未完~