一泛型介绍
1 .1 语法格式
<无意义的字符> 一般放
//无返回值 有参数的泛型方法
public static <T> void test(T t){
sout("t");
}
// 有返回值 有参数的泛型方法
public static <T> T test2(T t){
return t;
}
1.2 自定义泛型在类中使用
class 类名 <T>{
}
1.3 自定义泛型在接口中使用
interface 接口名字<T> {
}
案例一
interface demo <T>{
public T test(T t);//有参数有返回值的泛型类型
public void (T t);//有参数无返值类型。
// 在来一个类 去实现这个接口泛型的实现类
// 接口带有泛型,那么它的实现类必须带有泛型,而且你的泛型必须和接口的泛型一致
class demo1<T> implements demo<T>{
public void (T t){
System.out.println("hello world");
public T test(T t){
return a+b;
}
}
1.4 泛型在抽象类中使用
abstract demo <T> {
}
//案例一
abstract class B<T> {
public abstract void getArgs(T t);
public void get(T t) {
System.out.println(t);
}
public abstract T getArgs1(T t);
}
class TestB<T> extends B<T> {
@Override
public void getArgs(T t) {
// TODO Auto-generated method stub
System.out.println(t);
}
@Override
public void get(T t) {
// TODO Auto-generated method stub
System.out.println(t);
}
@Override
public T getArgs1(T t) {
// TODO Auto-generated method stub
return t;
}
}
public class Demo6 {
public static void main(String[] args) {
TestB<String> testB = new TestB<String>();
testB.getArgs("bh");
}
}
二 集合
2.1 Collection 和Collections的区别?
Collection : 是list 和set集合的父类。
Collections: 是集合的工具类
Collection<E>中的方法,遵从Collection接口的实现类或者子接口都可以使用这些方法。
增:
boolean add(E e);添加指定的元素到指定的集合中,采用的尾插法
boolean addAll(Collection<? extends E>);添加另外一个集合到当前集合对象中。要求添加的对象集合的泛型和当前对象集合保持一致
删:
boolean remove(Object obj);删除集合中的某一个元素。
boolean removeAll(Cololection<? extends E> e);删除两个集合中的交集
void clear();清空所有的元素
查:
int size();获取集合中元素的个数
Object[] toArray();将集合转为Object类型的数组
boolean contains(Object o);判断数据是否在集合中
boolean containsAll(Cololection<? extends E> e);判断一个集合是否是另外一个集合的子集合
boolean isEmpty();判断元素是否为空
2.2 list 集合
list 集合特点 : 有序元素可以重复
2.2.1 ArraysList 和LinkedList
ArraysList: 是基于数组的实现。默认容器量为10 ,一旦这个集合的容器量不足,就会自动扩容,使用是低层代码grow。是扩容原来的1.5倍。
ArraysList 有一些特征: 查找快,增删慢。
LinkedList : 是基于数组+链表的实现。第一个元素没有前置节点,最后的元素没有后继。连接元素 是通过前面元素的后继 跟第二个元素的前置进行连接
所以 查找慢 增删快。
2.3 Set 集合
set 接口里面实现的子类有 hashset treeset
set 集合特征 : 无序 元素不能重复。
/**
* hashSet是基于hashMap(哈希表)实现
* 不允许有重复元素 可以又一个null元素
* 添加元素是把元素值作为hashMap的key
* 排除元素重复是通过equals来检查对象是否相同
* 判断两个对象是否相同,先判断两个对象hashcode是否相同 如果两个hashcode相同,不一定是相同对象
* 如果两个对象的equals相同 则一定hashcode相同;
* 2 hashcode 是基于数组加链表,数组中每个元素以链表的方式存储数据;
*
*/
/**
* 由此可见:treeSet是有序的 元素不能重复
*/
2.4 Map 集合
1 将映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射一个值
2 以键值对方式存储一对对象 Key不能重复 Value可以重复
3 具体实现类有 : hashMap TreeMap Hashtable
2.4.1 map集合遍历方式
package com.mmc.g_map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* map接口:
* 以key—value存储数据 key不能重复 value可以重复
* 实现的接口有 hashMap treeMap Hashtable;
*/
public class MapDemo {
private static void getHashMap(){
Map<Integer,String> map = new HashMap<>();
map.put(1,"hello");
map.put(2,"world");
map.put(3,"good");
map.put(4,"morning");
map.put(5,"afternoon");
/*
1 通过entrySet进行集合遍历
*/
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
entrySet.forEach((s)-> System.out.println(s.getValue()));
/*
2 通过keyset遍历
*/
Set<Integer> keys =map.keySet();
for (Integer i : keys) {
String value = map.get(i);
System.out.println(i+"-->"+value);
}
/*
3 直接遍历values
*/
Collection<String> vaules=map.values();
for (String va:vaules) {
System.out.println(va);
}
/*
4 foreach 是实现 BiConsumer这个接口 传两个参数
*/
map.forEach((key,vaule)-> System.out.println(key+"-->"+vaule));
}
public static void main(String[] args) {
getHashMap();
}
}
2.4.2 HashMap实现原理
/**
* map接口:
* 以key—value存储数据 key不能重复 value可以重复
* 实现的接口有 hashMap treeMap Hashtable;
* 二 HashMap实现原理
* hashMap是基于数组加链表 在jdh1.8之后是以数组加链表加红黑树实现的
* static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;默认加载因子为0、75 默认数组大小为16 1左移4 相当于2的4次方
* 三 把对象如何存入哈希表中;
* 把key对象通过hash()的方法计算hash值,然后这个长度对数组取余(默认长度16);然后来确定key在数组中位子,如果有相同的key
* 的对象时,以链表结构存储;在jdk8后 当存储达到链表长度大于8。就会转换为红黑树结构存储;
* 四 当数组容量达到0。75,如何扩充
* 将当前数组容量向左移一位,然后在根据hash()计算哈希值在数组中位置
* 五 线程不安全,适合在单线程使用
*/
三 匿名内部类
3.1 基于抽象类的匿名内部类
*** 之前的抽象类不能倍实例化,但是现在可以使用匿名内部类去实现实例化
package com.qfedu.c_anno;
//定义一个抽象类
abstract class Animal{
public abstract void eat();
}
//之前再新建一个类去继承Animal,然后重写eat方法
//
public class Demo1 {
public static void main(String[] args) {
//现在直接可以这样来写
// Animal animal = new Animal() {//实例化抽象类的时候顺便把未实现的方法实现掉
// @Override
// public void eat() {
// // TODO Auto-generated method stub
// System.out.println("吃饭");
// }
// };
// animal.eat();
new Animal() {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("在吃饭");
}
}.eat();//匿名对象.方法();
}
//官方文档中关于匿名内部类说过英文的 减少代码的量
}
package com.mmc.abstranct2;
/**
* 这一种方法在开发中常用
*/
public class StudentTest2 {
public static void main(String[] args) {
test(new Student() {
@Override
public void study() {
System.out.println("她在学后端知识");
}
});
}
public static void test(Student student){
student.study();
}
}
3.2 基于接口的匿名内部类
interface Pig {
public void eat();
}
//不用再单独写一个类去实现这个接口
public class Demo3 {
public static void main(String[] args) {
new Pig() {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("猪吃主食");
}
}.eat();
}
}
四 io流
4.1 io流的分类
4.1.1 按照流的功能方向分
1 输入流 和输出流
输入流:只能从中读取数据,不能写入数据
输出流: 只能从中写入数据,不能读取数据‘
4.1.2 按照流的角色分为
1 字节流和字符流
字节流:InputStream OutputStream 但是这个字节流没有缓存作用
如果想有缓存功能使用 BuffterInputStream 和 BuffterOutputStream。
字符流: Filewriter FileRead 没有缓存作用
Buffter 就具备缓冲作用。
4.2 File类几个判断方法
//是文件
System.out.println(new File("c:/aaa/1.txt").isFile());
System.out.println(new File("c:/aaa").isFile());//false
System.out.println(new File("c:/aaa").isDirectory());//true
System.out.println(new File("c:/aaa/1.txt").isDirectory());//false
System.out.println(new File("c:/aaa/1.txt").isHidden());//false
System.out.println(new File("c:/aaa/1.txt").isAbsolute());//true
System.out.println(new File("c:/aaa/8888.txt").exists());//false
4.3 使用流的方法copy文件
class test2{
public static void main(String[] args) throws IOException {
test4();
}
public static void test4() throws IOException{
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(new File("C:\\Users\\梅梦成07\\Desktop\\知识\\33.txt")));
BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream(new File("D:\\working1\\day20-File\\3.txt")));
long strat=System.currentTimeMillis();
byte[] bytes=new byte[1024];
int length=-1;
while ((length=bis.read(bytes))!=-1){
bos.write(bytes,0,length);
}
bos.close();
bis.close();
long end = System.currentTimeMillis();
System.out.println(end-strat);
}
}
五 多线程
5.1 进程和线程
进程: 进程是需要通过系统的分配,获取系统当前的CPU,内存,显卡,网络等这些资源
1.独立性
2.互斥性
线程: 线程是组成进程的最小基本单位,一个进程至少包含一个线程。
5.2 创建线程的方式
5.2.1 使用Thread
class MyThread1 extends Thread {
@Override
public void run() {
//for循环
for (int i = 0; i < 100; i++) {
System.out.println("我是Mythread1线程里面的代码");
}
}
}
class MyThread2 extends Thread {
@Override
public void run() {
//for循环
for (int i = 0; i < 100; i++) {
System.out.println("我是Mythread2线程里面的代码");
}
}
}
public class Demo1 {
public static void main(String[] args) {
//main一个线程
//实例化出来一个线程对象
MyThread1 myThread1 = new MyThread1();
//通过调用start方法开启线程一定是start方法
myThread1.start();
MyThread2 myThread2 = new MyThread2();
myThread2.start();
//4个线程 2个myThread 1main 1jvm 垃圾回收器
for (int i = 0; i < 100; i++) {
System.out.println("我是main主函数线程");
}
}
}
5.2.2 实现Runable接口
package com.qfedu.a_thread;
class MyThread4 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
System.out.println("MyThread" + i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
//第二种写法
Thread thread = new Thread(new MyThread4());
thread.start();//开启线程
for (int i = 0; i < 100; i++) {
System.out.println("main:" + i);
}
}
}
5.3 了解线程下面的方法
构造方法:
Thread()
分配一个新的Thread
对象。Thread(Runnable target)
分配一个新的Thread
对象。Thread(Runnable target, String name)
分配一个新的Thread
对象。 并对当前线程起个名字哦
成员方法:
static Thread currentThread();获取当前线程对象
String getName();获取当前线程名字的
void setName(String name);设置当前线程的名字
void setPriority(int newPriority);设置当前线程的优先级。这个优先级只会增加线程执行的概率
但是真正的会不会优先不一定。int类型的参数,所有线程默认的优先级是5 传值 1-10 1的优先级是最低的,10优先级是最高的
int getPriority();获取当前线程优先级的
现在大家想一个问题,线程不可控,乱抢。怎么解决这样的问题呢?现在的解决方案让其睡会,就不抢占了
static void sleep();让线程休眠多少毫秒
可以让线程睡一会儿来控制线程的执行的先后顺序的
在run方法中调用Thread.sleep();只能try-catch不能抛
5.4 锁
synchronised Java 的关键字 同步锁
咱们线程是不安全的,随机抢占的。能不能让其线程有规律的执行呢?
可以的就是加锁。一个线程抢到资源以后,加上锁以后,这个线程先执行结束,会自动的释放锁
其他线程会进行抢占
用法:
1.修饰一个代码块
2.修饰一个方法
3.修饰一个静态方法
4.修饰一个类
5.4.1 语法格式
synchronised (this) {
代码块
}
给线程上锁 可以保证当前的线程安全。
5.5 线程中 sleep(),join(),close(),strat();
sleep():因为线程之间具有抢占式,使用sleep关键字,可以保证当前的线程进行休眠、
join(): 开启线程是现执行主线程,然后在执行子线程,然后子线程结束,在执行主线程,至到结束。
close() : 线程比较耗jvm资源,所以要关闭掉
strat() 只有调用这个方法,线程才能执行。