目录
Java介绍
Java性质
Java是一门面向对象编程语言,运行在JVM(Java Virtual Machine,java虚拟机)上,实现了跨平台运行Java的功能。
Java平台(J2EE\J2SE\J2ME)
一、定义和应用范围:J2SE包含于J2EE中,J2ME包含了J2SE的核心类,但新添加了一些专有类 。
不同的组件构成了不同的J2EE\J2SE\J2ME
与spring一样,J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术,不是JDK类似的产品。
如果要从事JavaSE、JavaME、JavaEE平台开发,那么就要用到JDK进行开发。
比如陆地,天空,大海三大领域和建筑材料的关系,在陆地建房子需要建筑材料,在天空盖房子需要材料,在大海也需要材料,当然,不同领域还需要其他一些功能性材料添加一起。
1、j2se是java的桌面应用平台,用于开发桌面应用程序,比如qq,暴风影音都是桌面应用程序,其中s表示standard,标准的意思。
2、j2ee,其中的e表示enterprise,即企业是意思,即java企业应用平台,用于大型的分布式的开发程序。
3、j2me,m表示mobile,即移动平台,用于开发手机,嵌入cpu机器的开发平台。
二、应用领域:
1、针对企业网应用的J2EE(Java 2 Enterprise Edition);
2、针对普通PC应用的J2SE(Java 2 Standard Edition);
3、针对嵌入式设备及消费类电器的J2ME(Java 2 Micro Edition)。
三、做出来的东西即java程序:
1、 源文件扩展名.java;
2、对应文件编译后扩展名为.class;
3、打包后扩展名为.jar。
Java开发环境与运行环境
一、开发环境(java版本指开发环境版本,如JAVA8、JDK1.8都是开发环境版本)
JDK,Java Development Kit是 Java 语言的软件开发工具包(SDK)。JDK是整个java开发的核心,它包含了JAVA的运行环境JRE(JVM+Java系统类库)和JAVA工具。
jdk开发环境与组件(j2ee\j2se\j2me)不同,组件需要运行在开发环境或者运行环境中
openjdk:开源版
oraclejdk:商业版
两者在一些库中存在细微差别
二、运行环境
JRE(java的运行环境),能提供一切需要运行java应用程序的环境。能满足大多数终端用户的需求。
Java基础
数据类型
八大基本数据类型
四种整型、
1、int: 4 字节( -2 147 483 648 到 2 147 483 647 (正好超过 20 亿))
2、short: 2字节 (-32 768到32 767)
3、long:8字节 (-9 223 372 036 854 775 808 到 9 223 372 036 854 775 807)
4、byte:1字节 (-128到127)
两种浮点类型
5、float:4 字节 (大约 ± 3.402 823 47E+38F (有效位数为 6 ~ 7 位)),后缀有f
6、double:8字节(大约 ± 1.797 693 134 862 315 70E+308 (有效位数为 15 位))
一种字符类型
7、char:2字节 (与字符串String不同)
一种布尔类型
8、boolean (布尔):类型有两个值:false 和 true, 用来判定逻辑条件 整型值和布尔值之间不能进行相互转换。
Java规范并没有强制规定boolean所占用的内存单元,但由于大部分计算机最小内存分配单元为字节(8位),因此一个boolean类型常占用8位 = 1字节。
三大引用数据类型
引用类型继承于Object类,常通过new关键字来创建。引用类型存放在内存的堆中,可以在运行时动态的分配内存大小,生存期也不必事先告诉编译器,当引用类型变量不被使用时,Java内部的垃圾回收器GC会自动回收走。引用变量中存放的不是变量的内容,而是存放变量内容的地址。
一、类 Class
1.java.lang.String是java字符串类,每种基本类型数据都有其对应的一个包装类
2.枚举类
//键值对枚举
enum WeekDay{
A("Monday"),B("Sunday");
private final String day;
WeekDay(String day) {
this.day = day;
}
public String getDay(){
return day;
}
}
//普通枚举
enum Name{
LiSi,ZhangSan
}
//取键
System.out.println(WeekDay.A);
//取值
System.out.println(WeekDay.A.getDay());
//取值
System.out.println(Name.LiSi);
二、接口 Interface
java中一个类只能继承一个父类,但却可以实现多个接口。
1 ) 将类声明为实现给定的接口。
2 ) 对接口中的所有方法进行定义。
声明接口:public interface Comparable
要将类声明为实现某个接口, 需要使用关键字 implements:
class Employee implements Comparable
三、数组 Array
数组
//新建长度为100的数组,未初始化
int a = new int[100];
//新建数组并且初始化
int[] small Primes = { 2, 3, 5, 7, 11, 13 };
泛型数组
在未确定数组大小时,使用泛型类ArrayList可以运行时动态更改数组问题
ArrayList<Object> list = new ArrayList<Object>
list.add<Object>
list.remove(i)
集合
集合和数组的区别
集合分类
Collection
集合常用API
List和set区别
一、List
List的三大实现类:
ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
LinkedList:底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素
Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素
1.1ArrayList
简介
1、ArrayList是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
2、ArrayList继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
3、ArrayList实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。。
4、ArrayList实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
5、ArrayList实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
ArrayList继承与实现的接口关系
实现
ArrayList< Object > list = new ArrayList<>();
//访问方式一:随机访问(索引访问)(最快)
for (int i=0; i<list.size(); i++) {
list.get(i);
}
//访问方式二:迭代器访问 (最慢)
for(Iterator iter = list.iterator(); iter.hasNext(); ) {
iter.next();
}
//访问方式三:for循环遍历
for(Object obj:list);
1.2LinkedList
简介
1、LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
2、LinkedList 实现 List 接口,能对它进行队列操作。
3、LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
4、LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
5、LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
6、LinkedList 是非同步的。
LinkedList继承与实现的接口关系
实现
LinkedList< Object > list = new LinkedList<>();
//访问方式一:迭代器访问
for(Iterator iter = list.iterator(); iter.hasNext();)
iter.next();
//访问方式二:随机访问(最慢)
for (int i=0; i<list.size(); i++) {
list.get(i);
}
//访问方式三:for循环(推荐)
for (Integer integ:list)
;
1.3Stack(继承了Vector的类)
vector简介
1、Vector由数组实现。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。
2、Vector继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。
3、Vector实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
4、Vector实现了Cloneable接口,即实现clone()函数。它能被克隆。
和ArrayList不同,Vector中的操作是线程安全的。
Vector继承与实现的接口关系
实现
Vector<Object> vector = new Vector<>();
//访问方式一:迭代器访问(最慢)
Integer value = null;
Iterator<int> size = vector.iterator();
while(size.hasNext()){
value = size.next();
}
//访问方式二:随机访问(推荐)
Integer value = null;
int size = vector.size();
for (int i=0; i<size; i++) {
value = (Integer)vector.get(i);
}
//访问方式三:for循环
Integer value = null;
for (Integer integ:vector) {
value = integ;
}
//访问方式四:Enumeration遍历
Integer value = null;
Enumeration enu = vector.elements();
while (enu.hasMoreElements()) {
value = (Integer)enu.nextElement();
}
二、set
set存储的可以是不同类的对象
set的实现类:
HashSet:底层数据结构是哈希表(HashMap),线程不安全,不可以存储重复元素,不记录迭代顺序
LinkedHashSet:继承了HashSet的类,底层数据结构是链表和哈希表,不可以存储重复元素,线程不安全,由链表进行记录迭代顺序。
TreeSet:唯一继承了SortedSet的类,底层数据结构是红黑树,线程不安全,不可以存储重复元素,通过自然排序或者比较器排序对对象进行排序。
set的接口:
SortedSet:是接口,不可以存储重复元素,通过比较对象进行排序,实现该接口的类线程不安全。
2.1HashSet
HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相 等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。
HashSet set = new HashSet();//可以添加不同类型的对象
HashSet<Object> set = new HashSet<>(); //只可以添加同类型的对象
set.add(object);
set.remove(object);
set.add(object1);//set中存储顺序与插入顺序无关
//访问方式一:迭代器访问
Iterator it=h.iterator();
while(it.hasNext()){
Object o=it.next();
}
//访问方式二:循环访问
for(Object object : set){
}
2.2LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
LinkedHashSet set = new LinkedHashSet();//可以添加不同类型的对象
LinkedHashSet<Object> set = new LinkedHashSet<>(); //只可以添加同类型的对象
set.add(object);
set.remove(object);
set.add(object1);//set中存储顺序与插入顺序无关
//访问方式一:迭代器访问
Iterator it=h.iterator();
while(it.hasNext()){
Object o=it.next();
}
//访问方式二:循环访问
for(Object object : set){
}
2.3TreeSet
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0
自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。
obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是负数,则表明obj1小于obj2。
如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0
class Move implements Comparable{
int id;
String no;
public Move(int id,String no){
this.id = id;
this.no = no;
}
@Override
public int compareTo(Object o){
if(o instanceof Move){
int i = this.id - (((Move)o).id);
System.out.println(this.no+((Move)o).no);
return i;
}
return 0;
}
}
public class test {
public static void main(String [] args)
{
TreeSet<Move> set = new TreeSet<>();
set.add(new Move(1,"A4"));
set.add(new Move(5,"A5"));
set.add(new Move(3,"A7"));
set.add(new Move(4,"A8"));
}
}
定制排序
自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现int compare(T o1,T o2)方法
class Move {
int id;
String no;
public Move(int id,String no){
this.id = id;
this.no = no;
}
}
public class test {
public static void main(String [] args){
Comparator com = new Comparator(){
@Override
public int compare(Object m1,Object m2){
if(m1 instanceof Move && m2 instanceof Move){
Move mv1 = (Move)m1;
Move mv2 = (Move)m2;
int id = mv1.id - mv2.id;
return id;
}
return 0;
}
};
TreeSet<Move> set = new TreeSet<>(com);//传入comparator对象
set.add(new Move(1,"A4"));
set.add(new Move(5,"A5"));
set.add(new Move(3,"A7"));
set.add(new Move(4,"A8"));
for(Object object : set){
Move m = (Move)object;
}
}
}
Map
Map的对象为键值对,Key-Value
Map的三大实现类:
HashTable:继承于Dictionary类,实现了Map接口,底层数据结构是哈希表,线程同步,线程安全,性能差,不能放入空值。
HashMap:底层数据结构是哈希表,线程异步,线程不安全,性能好,可以放入一个Key值为Null,多个Value值为Null。
TreeMap:实现了SortedMap接口的类,底层数据结构是二叉树,非线程安全基于红黑树实现。
一、HashTable
public class Test {
public static void main(String [] args){
int val = 0;
String key = null;
String value = null;
Random r = new Random();
Hashtable<Object1,Object2> table = new Hashtable<>();//创建指定Key和Value类型的table
Hashtable table = new Hashtable();
for (int i=0; i<12; i++) {
// 随机获取一个[0,100)之间的数字
val = r.nextInt(100);
key = String.valueOf(val);
value = String.valueOf(r.nextInt(5)) ;
// 添加到Hashtable中
table.put(key, value);
System.out.println(" key:"+key+" value:"+value);
}
table.put("name","LiHua");
// 通过entrySet()遍历Hashtable的key-value
iteratorHashtableByEntryset(table) ;
// 通过keySet()遍历Hashtable的key-value
iteratorHashtableByKeyset(table) ;
// 单单遍历Hashtable的value
iteratorHashtableJustValues(table);
// 遍历Hashtable的Enumeration的key
enumHashtableKey(table);
// 遍历Hashtable的Enumeration的value
enumHashtableValue(table);
}
/*
* 通过Enumeration遍历Hashtable的key
* 效率高!
* 第一步:根据keys()获取Hashtable的集合。
* 第二步:通过Enumeration遍历“第一步”得到的集合。
*/
private static void enumHashtableKey(Hashtable table) {
if (table == null)
return ;
System.out.println("\nenumeration Hashtable");
Enumeration enu = table.keys();//接口实例化时须使用实现了该接口的类
while(enu.hasMoreElements()) {
System.out.println(enu.nextElement());
}
}
/*
* 通过Enumeration遍历Hashtable的value
* 效率高!
* 第一步:根据elements()获取Hashtable的集合。
* 第二步:通过Enumeration遍历“第一步”得到的集合。
*/
private static void enumHashtableValue(Hashtable table) {
if (table == null)
return ;
System.out.println("\nenumeration Hashtable");
Enumeration enu = table.elements();
while(enu.hasMoreElements()) {
System.out.println(enu.nextElement());
}
}
/*
* 通过entry set遍历Hashtable
* 效率高!
* 第一步:根据entrySet()获取Hashtable的“键值对”的Set集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashtableByEntryset(Hashtable table) {
if (table == null)
return ;
System.out.println("\niterator Hashtable By entryset");
String key = null;
String integ = null;
Iterator iter = table.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = (String)entry.getKey();
integ = (String)entry.getValue();
System.out.println(key+" -- "+integ);
}
}
/*
* 通过keyset来遍历Hashtable
* 效率低!
* 第一步:根据keySet()获取Hashtable的“键”的Set集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashtableByKeyset(Hashtable table) {
if (table == null)
return ;
System.out.println("\niterator Hashtable By keyset");
String key = null;
String integ = null;
Iterator iter = table.keySet().iterator();
while (iter.hasNext()) {
key = (String)iter.next();
integ = (String)table.get(key);
System.out.println(key+" -- "+integ);
}
}
/*
* 遍历Hashtable的values
* 第一步:根据value()获取Hashtable的“值”的集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashtableJustValues(Hashtable table) {
if (table == null)
return ;
Collection c = table.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
二、HashMap
import java.util.Map;
import java.util.Random;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Collection;
/*
* @desc 遍历HashMap的测试程序。
* (01) 通过entrySet()去遍历key、value,参考实现函数:
* iteratorHashMapByEntryset()
* (02) 通过keySet()去遍历key、value,参考实现函数:
* iteratorHashMapByKeyset()
* (03) 通过values()去遍历value,参考实现函数:
* iteratorHashMapJustValues()
*/
public class timeTest {
public static void main(String[] args) {
int val = 0;
String key = null;
Integer value = null;
Random r = new Random();
HashMap map = new HashMap();
for (int i=0; i<12; i++) {
// 随机获取一个[0,100)之间的数字
val = r.nextInt(100);
key = String.valueOf(val);
value = r.nextInt(5);
// 添加到HashMap中
map.put(key, value);
System.out.println(" key:"+key+" value:"+value);
}
// 通过entrySet()遍历HashMap的key-value
iteratorHashMapByEntryset(map) ;
// 通过keySet()遍历HashMap的key-value
iteratorHashMapByKeyset(map) ;
// 单单遍历HashMap的value
iteratorHashMapJustValues(map);
}
/*
* 通过entry set遍历HashMap
* 第一步:根据entrySet()获取HashMap的“键值对”的Set集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashMapByEntryset(HashMap map) {
if (map == null)
return ;
System.out.println("\niterator HashMap By entryset");
String key = null;
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = (String)entry.getKey();
integ = (Integer)entry.getValue();
System.out.println(key+" -- "+integ.intValue());
}
}
/*
* 通过keyset来遍历HashMap
* 第一步:根据keySet()获取HashMap的“键”的Set集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashMapByKeyset(HashMap map) {
if (map == null)
return ;
System.out.println("\niterator HashMap By keyset");
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
key = (String)iter.next();
integ = (Integer)map.get(key);
System.out.println(key+" -- "+integ.intValue());
}
}
/*
* 遍历HashMap的values
* 第一步:根据value()获取HashMap的“值”的集合。
* 第二步:通过Iterator迭代器遍历“第一步”得到的集合。
*/
private static void iteratorHashMapJustValues(HashMap map) {
if (map == null)
return ;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
三、TreeMap
TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。
API:
Entry<K, V> ceilingEntry(K key)
K ceilingKey(K key)
void clear()
Object clone()
Comparator<? super K> comparator()
boolean containsKey(Object key)
NavigableSet<K> descendingKeySet()
NavigableMap<K, V> descendingMap()
Set<Entry<K, V>> entrySet()
Entry<K, V> firstEntry()
K firstKey()
Entry<K, V> floorEntry(K key)
K floorKey(K key)
V get(Object key)
NavigableMap<K, V> headMap(K to, boolean inclusive)
SortedMap<K, V> headMap(K toExclusive)
Entry<K, V> higherEntry(K key)
K higherKey(K key)
boolean isEmpty()
Set<K> keySet()
Entry<K, V> lastEntry()
K lastKey()
Entry<K, V> lowerEntry(K key)
K lowerKey(K key)
NavigableSet<K> navigableKeySet()
Entry<K, V> pollFirstEntry()
Entry<K, V> pollLastEntry()
V put(K key, V value)
V remove(Object key)
int size()
SortedMap<K, V> subMap(K fromInclusive, K toExclusive)
NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive)
NavigableMap<K, V> tailMap(K from, boolean inclusive)
SortedMap<K, V> tailMap(K fromInclusive)
import java.util.*;
public class timeTest {
public static void main(String[] args) {
Comparator com = new Comparator(){//定制比较器排序
@Override
public int compare(Object m1,Object m2){
if(m1 instanceof Phone && m2 instanceof Phone){
Phone mv1 = (Phone)m1;
Phone mv2 = (Phone)m2;
int id = mv1.getPrice() - mv2.getPrice();
return id;
}
return 0;
}
};
TreeMap<Phone,String> map = new TreeMap<>(com);
map.put(new Phone("Apple",7000),"美国");
map.put(new Phone("Sony",5000),"日本");
map.put(new Phone("Huawei",6000),"中国");
Set<Phone> phones = map.keySet();
Iterator<Phone> iterator = phones.iterator();
while(iterator.hasNext()){
Phone next = iterator.next();
System.out.println(next.getBrand()+"==="+next.getPrice()+"==="+map.get(next));
}
}
}
//class Phone implements Comparable<Phone>{
class Phone {
private String Brand;
private int Price;
public Phone(String brand, int price) {
Brand = brand;
Price = price;
}
public String getBrand() {
return Brand;
}
public void setBrand(String brand) {
Brand = brand;
}
public int getPrice() {
return Price;
}
public void setPrice(int price) {
Price = price;
}
// @Override//自然排序
// public int compareTo(Phone o) {
// return this.getPrice() - o.getPrice();
// }
}
日期和时间
java.util.Date和java.sql.Date
java.util.Date 是在除了SQL语句的情况下使用,包含日期和时间部分
import java.util.Date
import java.text.SimpleDateFormat;
import java.text.ParseException;
Date day = new Date();//包含日期和时间,Date数据类型
//Date转String方式一:
String str_day = day.toString();// Thu Dec 31 15:56:33 CST 2020
//Date转String方式二:
//MM代表月,mm代表分,HH代表24小时进制,hh代表12小时进制
SimpleDateFormat SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String str_day = SDF.format(day);// 2020/12/31 15:54:20
//String转Date:
Date strToDate = SDF.parse(str_day); // Thu Dec 31 15:54:20 CST 2020
java.sql.Date 是针对SQL语句使用的,它只包含日期而没有时间部分
java.sql.Timestamp 为时间戳类,包含日期和时间部分
import java.sql.Date;
import java.text.SimpleDateFormat;
Date day = new Date(System.currentTimeMillis());//2020-12-31
//Date转String方式一:
String str_day = day.toString();//2020-12-31
//Date转String方式二:
SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str_day = SDF.format(day);//2020-12-31 15:59:43
//String转Date
Date strToDate = Date.valueOf(str_day.substring(0, 10))//只能转化yyyy-MM-dd的字符串
java.time.*
Java 8 中添加了一个全新的日期时间 API 位于 java.time 包中,主要变化是,自1970年1月1日以来,日期和时间现在不再由单个毫秒数表示,而是由1970年1月1日以来的秒数和纳秒数表示。
秒数既可以是正的,也可以是负的,用 long 表示。纳秒数始终为正,由 int 表示。
Java .time.Instant 类表示时间线上的一个特定时刻,被定义为自原点起的偏移量,原点是1970年1月1日00点格林,也就是格林尼治时间。 时间以每天 86400 秒为单位,从原点向前移动
import java.time.*;
Instant start = Instant.now();//2020-12-31T08:44:16.662649300Z
LocalDate today = LocalDate.now();//2020-12-31
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);//start和end的间隔,根据取值的类型判断是否
Long mills = timeElapsed.toMillis();
LocalDate birthday = LocalDate.of(1903,Month.JUNE,14);//1903-06-14
LocalDate progammersDay = LocalDate.of(2019,1,1).plusDays(255);//加255天
progammersDay = progammersDay.plus(Period.ofYears(1));//自动判断闰年等情况
LocalDate churchsBirthday = LocalDate.parse("1903-06-14");//通过字符串生成日期
对象与类
类( class) 是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的切割机,将对象想象为小甜饼。由类构造(construct) 对象的过程称为创建类的实例 (instance )。类可实现接口,接口不能实例化。
接口
public interface 接口名{
}
接口中只定义方法,不实现具体的方法,具体方法由实现的类中的方法实现。
一、作用域
1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用。
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用。
3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。
公有继承 继承自父类的成员保持不变。
私有继承 继承自父类的成员全部变为私有成员。
保护继承 继承自父类的公有成员变为保护成员,其余不变。
final实例域
将实例域定义为final后,构建对象时必须初始化这样的域,且不能再被修改。
private final String name;
二、静态域与静态方法(关键字Static)
1、静态方法:可以直接通过类名.方法名访问。(有静态方法的类,必须声明为静态类)
非静态方法:需要通过创建对象来访问方法。
2、静态方法:只可以访问静态成员(静态变量和静态方法)。
非静态方法:既可以访问实例也可以访问静态。
3、静态方法和静态类是随着类的加载而加载的。并且只加载一次。
匿名类
匿名类通过直接实例化抽象类并且实现其抽象方法,达到不声明另一个类进行继承匿名实现的效果
public abstract class Hero {
String name; //姓名
float hp; //血量
float armor; //护甲
int moveSpeed; //移动速度
public abstract void attack();
protected abstract void equip();
public static void main(String[] args) {
Hero h = new Hero(){
//当场实现attack方法
public void attack() {
System.out.println("新的进攻手段");
}
protected void equip(){
System.out.println("神装");
}
};
h.attack();
h.equip();
h.name = "火女";
//通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名
System.out.println(h+h.name);
}
}
本地类
本地方法内部的java类即为本地类,只在小范围内使用java类时推荐使用本地类
public abstract class Hero {
String name; //姓名
float hp; //血量
float armor; //护甲
int moveSpeed; //移动速度
public abstract void attack();
public static void main(String[] args) {
//与匿名类的区别在于,本地类有了自定义的类名
class SomeHero extends Hero{
public void attack() {
System.out.println( name+ " 新的进攻手段");
}
}
SomeHero h =new SomeHero();
h.name ="地卜师";
h.attack();
}
}
内部类
内部类分为静态内部类与非静态内部类
内部类:在类中再定义一个类
静态内部类:两个类的联系不强,但是又可能存在相互使用的情况
public class Hero {
public String name;
protected float hp;
private static void battleWin(){
System.out.println("battle win");
}
//敌方的水晶
static class EnemyCrystal{
int hp=0;
//如果水晶的血量为0,则宣布胜利
public void checkIfVictory(){
if(hp==0){
Hero.battleWin();
//静态内部类不能直接访问外部类的对象属性
//System.out.println(name + " win this game");
//只可以访问
}
}
}
public static void main(String[] args) {
//实例化静态内部类
Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
crystal.checkIfVictory();
}
}
非静态内部类:内部类必须依赖于外部类才有存在的意义
public class Hero {
private String name; // 姓名
float hp; // 血量
float armor; // 护甲
int moveSpeed; // 移动速度
// 非静态内部类,只有一个外部类对象存在的时候,才有意义
// 战斗成绩只有在一个英雄对象存在的时候才有意义
class BattleScore {
int kill;
int die;
int assit;
public void legendary() {
if (kill >= 8)
System.out.println(name + "超神!");
else
System.out.println(name + "尚未超神!");
}
}
public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
// 实例化内部类
// BattleScore对象只有在一个英雄对象存在的时候才有意义
// 所以其实例化必须建立在一个外部类对象的基础之上
BattleScore score = garen.new BattleScore();
score.kill = 9;
score.legendary();
}
}
lambda 表达式
Lambda 表达式是一种匿名函数(对 Java 而言这并不完全正确,但现在姑且这么认为),简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。
你可以将其想做一种速记,在你需要使用某个方法的地方写上它。当某个方法只使用一次,而且定义很简短,使用这种速记替代之尤其有效,这样,你就不必在类中费力写声明与方法了。
Lambda 表达式通常使用 (argument) -> (body) 语法书写
(String first, String second)
-> first.length() - second.length()
interface Operation {
int operate(int a,int b);
}
public class Hero{
public static void main(String[] args){
Operation add = (x,y) -> x+y;
Operation add2 = (x,y) -> x*x+y*y;
System.out.println(add2.operate(20, 10));
//System.out.println(operate(10,5,add));
}
/*
public static int operate(int a, int b, Operation operation) {
return operation.operate(a, b);
}*/
}
并发
线程
通常,每一个任务称为一个线程( thread), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序(multithreaded)。那么,多进程与多线程有哪些区别呢? 本质的区别在于每个进程拥有自己的一整套变量,而线程则共享数据。 这听起来似乎有些风险, 的确也是这样, 在本章稍后将可以看到这个问题。
然而,共享变量使线程之间的通信比进程之间的通信更有效、 更容易。 此外, 在有些操作系统中,与进程相比较, 线程更“ 轻量级”, 创建、 撤销一个线程比启动新进程的开销要小得多。
在实际应用中, 多线程非常有用。例如, 一个浏览器可以同时下载几幅图片。一个 Web服务器需要同时处理几个并发的请求。图形用户界面(GUI) 程序用一个独立的线程从宿主操作环境中收集用户界面的事件。
Thread继承自Object类,实现了Runnable Interfaces接口
线程状态
1、New(新创建)
new Thread(r)
2、Runnable(可运行)
调用start()方法//分配到时间片时才在运行状态
3、Blocked(被阻塞)
4、waiting(等待)
5、Timed waiting(计时等待)
6、Terminated(被终止)
- 因为run方法正常退出而自然死亡。
- 因为一个没有捕获的异常终止了run方法而意外死亡。
线程池
在一个应用程序中,我们需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念。
线程池:Java中开辟出了一种管理线程的概念,这个概念叫做线程池,从概念以及应用场景中,我们可以看出,线程池的好处,就是可以方便的管理线程,也可以减少内存的消耗。
那么,我们应该如何创建一个线程池那?Java中已经提供了创建线程池的一个类:Executor
线程池中的corePoolSize就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收,
maximumPoolSize就是线程池中可以容纳的最大线程的数量,
keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间,而util,就是计算这个时间的一个单位,
workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)。
threadFactory,就是创建线程的线程工厂,
最后一个handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。
第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
第二种DisCardPolicy:不执行新任务,也不抛出异常
第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
第四种CallerRunsPolicy:直接调用execute来执行当前任务
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,5,20, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
Jedis jedis = new Jedis("127.0.0.1",6379);
HashMap<String,String> map = new HashMap<>();
map.put("a","1000");
map.put("b","2000");
map.put("c","3000");
jedis.hmset("map",map);
Map<String,String> taskMap = jedis.hgetAll("map");
taskMap.forEach((key,value)->threadPoolExecutor.execute(new task(value)));
}
private static class task implements Runnable {
private final String number;
task(String number){
this.number = number;
}
public void run(){
int num = Integer.parseInt(number);
while(num!=0)
System.out.println(Thread.currentThread().getId()+" "+num--);
}
}