XML
XML 可扩展标记语言,EXtensible Markup Language
简化数据的存储和共享
两台计算机传输数据使用,
简化平台的变更==构建复杂数据结构
数据 * * 算法 * * *分离=====配置文件
基本语法
XMl的处理指令----解析引擎看的
<?xml vaerson="1.0" encoding= "UTF-8" ?>
开头标签可以加属性,但是结束标签不能加属性,属性可以用单引号也可以用双引号,一般情况下用双引号,但是当有双引号只能用单引号,保证属性格式统一/
大小写敏感的
只有起始标签是不行的,必须的有结束标签,
开始标签和结束标签之间,要么包含标签要么包含文本.什么都不包含的时候或者
一个XML,必须得有且一个根标签(不被其他标签包含得标签)
XML要求所有元素必须正确嵌套
实体引用===XML的转义字符
实体引用 字符 说明
< < 小于
> > 大于
&aops; ' 单引号
&quop; " 双引号
& & 与
CDATA块
格式:<![CDATA [文本内容]]>
特殊标签中的实体引用被忽略,所有内容被当成一块文本数据对待
<?xml version="1.0" encoding="UTF-8"?>
<list>
<emp id="1">
<name>张三</name>
<age>23</age>
<gender>男</gender>
<salary>3333</salary>
</emp>
<emp id="2">
<name>李四</name>
<age>24</age>
<gender>男</gender>
<salary>5555</salary>
</emp>
<emp id="3">
<name>王五</name>
<age>25</age>
<gender>34</gender>
<salary>4354</salary>
</emp>
<emp id="4">
<name>黄志宏</name>
<age>24</age>
<gender>男</gender>
<salary>10000</salary>
</emp>
<emp id="5">
<name>小六子</name>
<age>12</age>
<gender>男</gender>
<salary>1111</salary>
</emp>
</list>
SAX解析==逐行扫描,边扫描边解析
优点:解析可以立即开始,速度快,没有内存压力
缺点:不能对节点修改
DOM文档对象模型 === 把文档中的所有元素按照其出现的层次关系,解析成一个个Node节点(推荐)
优点:把XML文件在内存中构造树形结构,可以遍历和修改节点
缺点:如果过文件比较大,内存有压力,解析的时间长
使用dom解析XML文档
public class ParseXmlDemo {
public static void main(String[] args) {
/*
* 将emplist.xml文档中所有的员工信息解析出来,存入到List集合. 每个员工信息用一个Emp实例保存
*/
List<Emp> list = new ArrayList<Emp>();
/*
* 使用DOM解析XML的步骤
* 1:创建SAXReader
* 2:使用SAXReader读取xml文档,并生成对应的Document对象,该对象保存了该文档的所有数据及结构
* 这一步也是DOM解析耗时耗资源的地方
* 3:通过Document对象获取根元素
* 4:按照XML文档的结构从根元素开始主机获取子元素以达到遍历XML文档数据的目的
*/
try {
// 1:创建SAXReader对象(字符输入流)
SAXReader reader = new SAXReader();
// 2:读取xml文档
Document document = reader.read(new File("emplist.xml"));
// Document document = reader.read(new
// FileInputStream("emplist.xml"));都可以
/*
* 3:Document提供了获取根元素的方法 Element getRootElement()
*
* Element的每一个实例用于表示XML文档中的一个元素(一对标签), 其提供了用于获取该元素相关信息的一系列方法:
*
* String getName() 获取单签标签的名字
*
* String getText() 获取当前标签中间的文本
*
* Element element(String name) 获取当前标签中指定名字的子标签
*
* List elements() 获取当前标签中的所有子标签
*
* List elements(String name) 获取当前标签下所有指定名字的同名字标签
*
* Attribute attribute(String name)
* 获取指定名字的属性,Attribute的每一个实例用于表示一个标签中的一个属性,可以通过 它获取该属性的名字与对应的属性值
*
* String attributeValue(String name) 可以直接获取当前标签中指定名字的属性所对应的值
*
*/
Element root = document.getRootElement();// 获取跟标签,就是list标签
List<Element> empList = root.elements("emp");
/*
* 遍历每个<emp>标签,获取员工消息
*/
for (Element empEle : empList) {
// int id = Integer.parseInt(empEle.attribute("id").getValue());
int id = Integer.parseInt(empEle.attributeValue("id"));
// 获取<name>标签-->获取<name>标签中间的文本
String name = empEle.element("name").getText();
// 获取<age>标签-->获取<age>标签中间的文本
int age = Integer.parseInt(empEle.elementText("age"));
// 获取<gender>标签-->获取<gender>标签中间的文本
String gender = empEle.element("gender").getText();
// 获取<salary>标签-->获取<salary>标签中间的文本
int salary = Integer.parseInt(empEle.elementText("salary"));
// System.out.println(id + "," +name + ","+ age + "," + gender +
// "," + salary);
list.add(new Emp(id, name, age, gender, salary));
}
} catch (Exception e) {
e.printStackTrace();
}
for (Emp emp : list) {
System.out.println(emp);
}
}
}
dom4j生成xml文档
/**
* 生成XML的步骤:
* 1:创建一个Document对象,表示一饿空白文档
* 2:向Document中添加根元素.
* 3:向根元素中主机添加子元素,以形成XML文档的结构
* 4:创建XMLWriter
* 5:使用XMLWriter将Document对象写出以生成文档
*/
try{
//创建一个空白文档
Document doc = DocumentHelper.createDocument();
/*
* Document提供了添加根元素的方法:
* Element addElement(String name)
* 向当前文档中添加给定名字的根元素,并将其以一个Element实例形式返回,以便继续向根元素中追加操作
* 注意:该方法只能调用一次,因为一个文档只允许有一个根元素.IllegalAddException
*/
Element root = doc.addElement("list");
/*
* 将集合中每个员工信息以一个<emp>标签形式添加到根标签
*/
for(Emp emp : list){
//向根元素root<list>中添加<emp>的子标签
Element empEle = root.addElement("emp");
//向<emp>标签中添加子标签<name>
Element nameEle = empEle.addElement("name");
//向子标签<name>中添加文本
nameEle.addText(emp.getName());
//向<emp>标签中添加子标签<age>
Element ageEle = empEle.addElement("age");
ageEle.addText(emp.getAge()+"");
//向<emp>标签中添加子标签<gender>
Element genderEle = empEle.addElement("gender");
genderEle.addText(emp.getGender());
//向<emp>标签中添加子标签<salary>
Element salaryEle = empEle.addElement("salary");
salaryEle.addText(emp.getSalary()+"");
//添加属性:id
empEle.addAttribute("id", emp.getId()+"");
}
//创建XMLWriter
XMLWriter writer = new XMLWriter(
new FileOutputStream("myemp.xml"),OutputFormat.createPrettyPrint()
);
writer.write(doc);
writer.close();
}catch(Exception e){
e.printStackTrace();
}
线程池:
线程池主要有两个作用:
1:重用线程
线程若频繁的创建销毁会给线程调度带来不小的额外工作量,会降低性能
2:控制线程数量
线程数量过大,会导致系统资源开销大,每个线程都需要内存来得以运行.
还有一个问题是:过多的线程会导致CPU过度切换,导致整体的并发性能降低.
当有以上情况出现时,都应当使用线程池了管理线程
时间\日期操作
java.util.Date
Date的每一个实例用于表示一个确切的时间点,内部维护的一个long值,该值是UTC(1970年1月1日00:00:00)到当前Date表示的时间之间所经过 的毫秒
由于Date存在始去以及千年虫问题,所以大部分的放啊发再JDK1.1版本推出时就被声明为过时的,而这些操作时间的方法都被Calendar的相关方法取代.
//默认创建表示当前系统时间;
Date date = new Date();
System.out.println("当前系统时间:" + date);//Tue Aug 21 09:55:37 GMT+08:00 2018
System.out.println(date.getYear()+1900);
/*
* long getTime()
* 获取Date内部维护的long值
*/
long time = date.getTime();
System.out.println("当前的long:" + time);
/*
* 获取明天这个时间
*/
time = time + 1000 * 60 * 60 * 24;
/*
* void setTime(long time)
* 设置一个long值,使Date表示该日期
*/
date.setTime(time);
System.out.println("明天的这个时候:" + date);
java.text.SimpleDateFormat
可以按照一个指定的日期格式将Date于String进行相互转换
Date date = new Date();
System.out.println(date);
/*
* Tue Aug 21 10:34:30 GMT+08:00 2018
* MM dd HH:mm:ss yyyy
*/
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//2018-08-21 10:34:30 上午 星期二
/*
* String format(Date date)
* 将给定的Date按照当前SDF指定的日期格式转换为字符串
*/
String line = sdf.format(date);
System.out.println(line);
将字符串解析为Date
String line = "2018-08-08 20:43:35";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(line);
System.out.println(date);
Calendar(抽象类)java.util.Calendar 日历类
Calendar本身是一个抽象类 ,不可实例化,但是提供了一个实现的静态方法:getInstance,可以根据当前系统所在的地区获取一个使用的实现类的实例,
大部分读取获取回来的都是格里高利历GregorianCalendar,即阳历
//获取Calendar默认表示当前系统时间
Calendar calendar = Calendar.getInstance();
//Calendar的toString不能直观反映出具体表示的日期
System.out.println(calendar);
/**
* Date getTime()
* Calendar的getTime()方法可以将其表示的时间以一个Date实例形式放回
*/
Date date = calendar.getTime();
System.out.println("当前时间信息:" + date);
//java.util.GregorianCalendar[time=1534832195639,areFieldsSet=true,
areAllFieldsSet=true,lenient=true,zone=sun.util.calenda
r.ZoneInfo[id="GMT+08:00",offset=28800000,dstSavings=0,useDaylight=f
alse,transitions=0,lastRule=null],firstDayOfWeek=1,minima
lDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=7,WEEK_OF_YEAR=
34,WEEK_OF_MONTH=4,DAY_OF_MONTH=21,DAY_OF_YEAR=233,DAY_O
F_WEEK=3,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MI
NUTE=16,SECOND=35,MILLISECOND=639,ZONE_OFFSET=28800000,DST_OFFSET=0]
//当前时间信息:Tue Aug 21 14:16:35 GMT+08:00 2018
/**
* void setTime()
* 使用当前Calendar表示给定的Date所表示的日期
* Date->Calendar
*/
calendar.setTime(date);
Calendar可以获取各个时间分量的值
int get(int field)
不同的时间分量用不同的数字表示,这些数字无需记忆,Calendar都提供了对应的常量
Calendar calendar = Calendar.getInstance();
//获取年
int year = calendar.get(Calendar.YEAR);
//获取月(从0开始)
int month = calendar.get(Calendar.MONTH) + 1;
//获取日
/**
* 和"天"有关的常量
* DAY_OF_YEAR 年中的天
* DAY_OF_MONTH 月中的天
* DAY_OF_WEEK 周中的天
* DATE 月中的天,于DAY_OF_MONTH一致
*/
int day = calendar.get(Calendar.DAY_OF_MONTH);
//int day = calendar.get(Calendar.DATE);
//获取小时
int hours = calendar.get(Calendar.HOUR_OF_DAY);//24小时制
//int hours = calendar.get(Calendar.HOUR);//12小时制
//分钟
int mimute = calendar.get(Calendar.MINUTE);
//秒
int second = calendar.get(Calendar.SECOND);
System.out.println(year + "-" + month + "-" + day + " " + hours + ":" + mimute + ":" + second);
//周几?
int dow = calendar.get(Calendar.DAY_OF_WEEK);
String[] data = {"日","一","二","三","四","五","六"};
System.out.println("周" + data[dow-1]);
//今年的第几天?
int doy = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println("今天是今年的第" + doy + "天");
//指定时间分量能够获取的最大值
int days = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
System.out.println("今年总共有" + days + "天");
Calendar提供了;
void set(int field ,int value)
对给定的时间分量设置给定的值
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());//Tue Aug 21 15:27:33 GMT+08:00 2018
calendar.set(Calendar.YEAR, 2008);
calendar.set(Calendar.MONTH , 7);//从0开始
calendar.set(Calendar.DAY_OF_MONTH,22);
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 25);
calendar.set(Calendar.SECOND, 20);
System.out.println(calendar.getTime());//Mon Sep 22 08:25:20 GMT+08:00 2008
void add(int field , int amount)
对给定的时间分量加上给定的值,若给定的值为负数,则是减去对应的值
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
/*
* 3年2个月零25天以后是哪天?
*/
calendar.add(Calendar.YEAR, 3);
calendar.add(Calendar.MONTH, 2);
calendar.add(Calendar.DAY_OF_YEAR, 25);
System.out.println(calendar.getTime());
//3年2个月零25天以后的周三是几月几号
calendar.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
System.out.println(calendar.getTime());
Lambda
lambda表达式是jdk1.8之后推出的一个新特性,可以更加简洁的创建匿名内部类,
使用lambda创建匿名内部类时要求该接口必须有且只有一个抽象方法时才可以使用.
lambda语法:
(参数列表)->{
方法体
}
使用lambda无需指定实现的接口,以及重写方法,编译器回结合当前源码分析并自动判别.注意,lambda也是编译器认可了最终会被编译器改为传统方式创建
//匿名内部类
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
//lambda形式创建
Runnable r2 = ()->{
System.out.println("hello");
};
//{}中间只有一句表达式,可以省略
Runnable r3 = ()->System.out.println("hello");
List<String> list = new ArrayList<String>();
list.add("小仓");
list.add("玛利亚");
list.add("齐天大圣");
/*
* 匿名内部类实现比较器
*/
/*Comparator<String> com = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};*/
==========================================
/*Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});*/
/*
* lambda形式
*/
/*Comparator<String> com = (String o1 ,String o2)->{
return o1.length() - o2.length();
};*/
/*Collections.sort(list, (Comparator<String>) (String o1 ,String o2)->{
return o1.length() - o2.length();
});*/
===========================================
/*
* 方法中参数的类型可以不指定,忽略{}的同时,若方法中有return,则return关键字也要忽略
*/
/*Comparator<String> com = (o1,o2)-> o1.length() - o2.length();*/
Collections.sort(list, (Comparator<String>) (o1 , o2)->o1.length() - o2.length());
//Collections.sort(list, com);
System.out.println(list);
JDK8之后,集合和Map都提供了一个方法,使用lambda方式遍历元素,
并且若该集合或Map是线程安全的,那么这种遍历方式于元素增删也是并发安全的.
曾经使用迭代器遍历时我们介绍过,迭代器遍历集合不与集合自身增删元素互斥,
并发操作需要自行维护同步,而新的这种遍历方式无需这样做
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.forEach((e)->{System.out.println(e);});
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("语文", 98);
map.put("数学", 100);
map.put("英语", 88);
map.forEach((k,v)->{System.out.println(k+ ":" +v);});