Java学习第五周

前言

本文记录了java第五周的学习,内容包括date的三代日期,list和map,以及io的开头

一、Date类

一共有三代日期

1丶第一代日期类

1.获取当前时间

代码如下

 //第一代日期
        Date d1=new Date();//获取当前系统时间,精确到秒
        System.out.println(d1);

输出的时候输出的是国外的时间格式

Wed Jun 01 08:29:03 CST 2022

进程已结束,退出代码0

2.日期格式转换

正因为输出的时候输出的是国外的时间格式,我们看起来不方便,所以用到了日期格转换

 //第一代日期
        Date d1=new Date();//获取当前系统时间,精确到秒
        System.out.println(d1);
        //日期格式转换
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");//创建格式,格式里面的字母不是乱写的
        String s1=sdf.format(d1);//使用字符串接受按照创建好的格式输出的对象
        System.out.println(s1);

输出对比如下:

Wed Jun 01 08:36:16 CST 2022
2022060108:36:16 星期三

进程已结束,退出代码0

也可以把一个格式化的字符串转化为原来的格式,代码如下:

 //日期格式转换
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");//创建格式
        String s1=sdf.format(d1);//使用字符串接受按照创建好的格式输出的对象
        System.out.println(s1);
        //把上述转化好的字符串转化回去
        Date parse=sdf.parse(s1);
        System.out.println(parse);

输出结果

2022060108:42:04 星期三
Wed Jun 01 08:42:04 CST 2022

转化成功

2丶Calendar第二代日期类

主要用它可以方便的进行日期的计算

1.创建

这个类是一个抽象类,我们无法直接建立他的对象,建立的时候用到了getInstance方法,代码如下

   Calendar calendar = Calendar.getInstance();//默认是当前日期

2.set创建一个指定日期的Calendar对象

     //set创建一个指定日期的Calendar对象
        calendar.set(2022, 5, 9);//这里的month写的是五月,实际上显示出来是6月
        System.out.println(calendar.getTime());//Thu Jun 09 09:11:21 CST 2022

上面是以下设置三个,年月日,我们也可以利用字段单独设置年月日
比如代码如下

	calendar.set(Calendar.YEAR,2021);
    calendar.set(Calendar.MONTH,11);
    calendar.set(Calendar.DAY_OF_MONTH,6);

3.使用get获取时间

代码如下

 Calendar calendar = Calendar.getInstance();//默认是当前日期
        //set创建一个指定日期的Calendar对象
        calendar.set(2022, 5, 9);//这里的month写的是五月,实际上显示出来是6月
        System.out.println(calendar.getTime());//Thu Jun 09 09:11:21 CST 2022
        System.out.println(calendar.get(Calendar.YEAR));//2022
        System.out.println(calendar.get(Calendar.MONTH));//5
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//9

注意, Calendar没有专门的格式化方法,所以需要我们自己去组合,某种意义上更方便了.

4.Date和Calendar互相转换

  1. Date转Calendar
Date date = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

2.Calendar转Date

Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR,2021);
    calendar.set(Calendar.MONTH,11);
    calendar.set(Calendar.DAY_OF_MONTH,6);
    calendar.add(Calendar.DAY_OF_MONTH,2);
    Date time = calendar.getTime();

3丶第三代日期类

这个类是jdk8以后才有的

1.创建

代码如下

  //创建第三代日期
        LocalDateTime ldt=LocalDateTime.now();
        System.out.println(ldt);

2.格式化

		 //创建第三代日期
        LocalDateTime localDateTime=LocalDateTime.now();
        System.out.println(localDateTime);
        //2.使用DateTimeFormatter对象来进行格式化
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = dtf.format(localDateTime);
        System.out.println("格式化的日期:" + format);

输出结果

2022-06-01T09:40:29.896
格式化的日期:2022-06-01 09:40:29

3.get获取具体内容

//创建第三代日期
        LocalDateTime localDateTime=LocalDateTime.now();
        System.out.println(localDateTime);
        //2.使用DateTimeFormatter对象来进行格式化
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = dtf.format(localDateTime);
        System.out.println("格式化的日期:" + format);
        System.out.println("年=" + localDateTime.getYear());
        System.out.println("月=" + localDateTime.getMonth());//英文版
        System.out.println("月=" + localDateTime.getMonthValue());//中文版
        System.out.println("日=" + localDateTime.getDayOfMonth());
        System.out.println("时=" + localDateTime.getHour());
        System.out.println("分=" + localDateTime.getMinute());
        System.out.println("秒=" + localDateTime.getSecond());

运行结果

2022-06-01T09:42:27.703
格式化的日期:2022-06-01 09:42:27=2022=JUNE
月=6=1=9=42=27

进程已结束,退出代码0

4.plus和minus方法

第三代日期提供了plus和minus方法可以对当前时间进行加或减
代码如下


        //看看666天后,是什么时候
        LocalDateTime localDateTime1 = localDateTime.plusDays(666);
        System.out.println("666天后:" + dtf.format(localDateTime1));

        LocalDateTime localDateTime2 = localDateTime.minusMinutes(2022);
       System.out.println("2022分钟前 日期为:" + dtf.format(localDateTime2));

运行结果

666天后:2024-03-28 09:46:24
2022分钟前 日期为:2022-05-31 00:04:24

以上就是三代日期的学习总结

二、集合

1丶集合的优势

我认为集合是数组的升级版,相比于数组有许多优势;
1:可以动态保存任意多个对象,比较方便
2:提供了一系列方便的操作对象的方法(add,remove等);
3:使用集合添加删除元素的代码很简洁;

2丶集合框架体系图

这里我从韩顺平老师视频里面截了两张关系图放在这里。
集合主要分为双列集合和单列集合
先放双列集合的图,如下
在这里插入图片描述
再放单列集合的关系图,如下
在这里插入图片描述

下面我具体展开说一下;

3丶collection接口

单列集合,我们知道接口就是一种规范,他的两个子类list和set实现了他的规范。来看一下他的两个子类的区别
List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
Set:无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。
来看一下具体区别!

List接口

List是元素有序并且可以重复的集合。
List的主要实现:ArrayList, LinkedList, Vector。

常用方法

1.add()
向List集合中添加元素

     list.add("孙千博");
		System.out.println(list);

输出:[孙千博]
2.size()
获取集合中有多少个元素

 int length = list.size();
		System.out.println(length);

输出:1
3.get()
获取指定位置的元素(从0开始计数)

		list.add("孙千博");
		list.add("张三");
		list.add("李四");
		System.out.println(list.get(2));

输出:李四
4.add(int i,String str)
在指定位置添加元素,原来此位置的元素后移。

		list.add("孙千博");
		list.add("张三");
		list.add("李四");
		list.add(0,"帅气学长");
		System.out.println(list.get(2));

输出:张三
5.set(int i,Object element)
替换指定位置的元素

		list.add("孙千博");
		list.add("张三");
		list.add("李四");
		list.set(2,"帅气学长");
		System.out.println(list.get(2));

输出:帅气学长
6.clear()
清空List集合中的所有元素,不做演示了这个,就是把现有的元素清空
7.isEmpty()
判断集合中是否为空,返回boolean类型。集合为空,返回true;否则返回false。
8.contains(Object o)
判断集合中是否含有特定元素
没有返回false,否则返回true

list.add("孙千博");
		list.add("张三");
		list.add("李四");
		boolean flag = list.contains("faker");
		System.out.println(flag);

输出:
false
9.remove(int i)
删除指定位置的元素,并将此元素返回,并且后面元素前移。

list.add("孙千博");
		list.add("张三");
		list.add("李四");
		list.set(2,"帅气学长")
		String str = list.remove(0);
		System.out.println(list);

输出:
[张三,帅气学长]
10.remove(Object o)
删除List集合中的某个特定元素,返回boolean类型,删除成功返回true,否则返回false,删除成功后,后面元素前移。跟上面的差不多,不做展示。

ArrayList, LinkedList, Vector的选择

简单来说,可以总结为以下:
增删多,LinkedList
改查多,ArrayList
ArrayList不同步,非线程安全,效率高,支持随机访问。 查询快,增删慢
LinkedList 不同步,非线程安全,效率高。查询慢,增删快
Vector同步,线程安全,效率低。查询快,增删慢

遍历的三种方式

1.普通for
2.增强for
3.迭代器iterator
三种方式的演示代码如下

import java.util.ArrayList;
import java.util.Iterator;

public class java0504 {
    public static void main(String[] args) {
        ArrayList<String> list =new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        //第一种方式,普通for
        for(int i=0;i<list.size();i++) {
            System.out.println(list.get(i));
        }
        //增强for
        for(String name:list) {
            System.out.println(name);
        }
        //迭代器
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

这三种方式都可以正确遍历集合中所有元素,结果太长了就不展示了(影响观看)
下面来说说在遍历的时候如果要增删元素应该怎么办

遍历时增删注意事项
细说普通for遍历

当我们用第一种方式增删元素时候

  ArrayList<String> list =new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            if (s.equals("b")) {
                list.remove(s);
            }
        }
        System.out.println(list);

输出结果

[a, c, d, e, f]

我们可以看到,b被删除了
但是这种方式有一个缺点,当代码中有两个b紧靠着的时候,它只会删除第一个b,原因是当第一个元素b被删除后,它后面所有的元素都向前移动了一个单位,循环时导致第二个元素b漏掉了

细说增强for遍历
     ArrayList<String> list =new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        for (String s : list) {
            if (s.equals("b")) {
                list.remove(s);
            }
            System.out.println(s);
        }

这种方式如果我们在遍历的时候增删元素会报错(ConcurrentModificationException),错误信息如下

a
b
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886)
	at java.util.ArrayList$Itr.next(ArrayList.java:836)
	at java_5.java0504.main(java0504.java:15)

进程已结束,退出代码1

简单来说,是因为在这里,foreach循环遍历容器本质上是使用迭代器进行遍历的,会对修改次数modCount进行检查,不允许集合进行更改操作
所以,在增删元素时候不能用增强for

细说迭代器遍历

先说一下结论,使用迭代器会避免以上两种错误
代码如下

  ArrayList<String> list =new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("d");
        list.add("e");
        list.add("f");
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if (s.equals("b")) {
                it.remove();
            }
        }
        System.out.println(list);
[a, d, e, f]

所以,我们以后如果想要在遍历的时候增删元素,推荐使用迭代器哦~

set接口

Set集合元素无序(存入和取出的顺序不一定一致),并且没有重复对象。
Set的主要实现类:HashSet, TreeSet。

常用方法

因为都是继承的collection接口,所以set接口里面的方法和list差不多,这里不做重复说明啦!

HashSet、TreeSet、LinkedHashSet的选择

一:HashSet
1.不能保证元素的排列顺序,顺序有可能发生变化
2.不是同步的,非线程安全
3.集合元素可以是null,但只能放入一个null

二:LinkedHashSet
1.LinkedHashSet中不能有相同元素,可以有一个Null元素,元素严格按照放入的顺序排列。
2.LinkedHashSet如何保证有序和唯一性?
1).底层数据结构由哈希表和链表组成。
2).链表保证了元素的有序即存储和取出一致,哈希表保证了元素的唯一性。
3.添加、删除操作时间复杂度都是O(1)。
4.非线程安全

三:TreeSet
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0

自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。

定制排序
自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法
1.TreeSet是中不能有相同元素,不可以有Null元素,根据元素的自然顺序进行排序。
2.TreeSet如何保证元素的排序和唯一性?
底层的数据结构是红黑树(一种自平衡二叉查找树)
3.添加、删除操作时间复杂度都是O(log(n))
4.非线程安全

4丶Map接口

说明

Map是双列集合
Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap,关系类图已经在一开始给出(上面)

Map常用方法

1.put(key,value)
向集合中添加元素

	scores.put("Tom", 100);//添加数据
	scores.put("Kate", 60);
    scores.put("Jim", 60);

2.size()
返回集合的长度
3.get(key)
输入key返回对应value,也可用于验证集合中是否有key,指定的键不存在的时候,返回的是null。

在这里插 Map<String,String> sqb = new HashMap<String,String>();
        sqb.put("Tom", "60");//添加数据
        sqb.put("Kate", "80");
        sqb.put("Jim","70");
        System.out.println(sqb.get("Tom"));入代码片

输出结果

60

进程已结束,退出代码0

4.replace(key,value),替换
通过key更新value,之前的就没有了

  public static void main(String[] args) {
        Map<String,String> sqb = new HashMap<String,String>();
        sqb.put("Tom", "60");//添加数据
        sqb.put("Kate", "80");
        sqb.put("Jim","70");
        System.out.println(sqb.get("Tom"));
        sqb.replace("Tom","70");
        System.out.println(sqb.get("Tom" ));
    }

输出结果,可以看到已经替换成功了

60
70

进程已结束,退出代码0

5.isEmpty()
判断集合中是否有元素,若有则返回true;若没有,则返回false
6.clear()
清空集合中的所有元素
7.remove()
根据key移除map中的与该key对应的value
代码如下

 public static void main(String[] args) {
        Map<String,String> sqb = new HashMap<String,String>();
        sqb.put("Tom", "60");//添加数据
        sqb.put("Kate", "80");
        sqb.put("Jim","70");
        System.out.println(sqb.get("Tom"));
        sqb.replace("Tom","70");
        System.out.println(sqb.get("Tom" ));
        sqb.remove("Tom");
        System.out.println(sqb.get("Tom"));
    }

输出结果

60
70
null

进程已结束,退出代码0

8.values()
获取Map集合所有的value

public class java0505 {
    public static void main(String[] args) {
        Map<String,String> sqb = new HashMap<String,String>();
        sqb.put("Tom", "60");//添加数据
        sqb.put("Kate", "80");
        sqb.put("Jim","70");
        System.out.println(sqb.values());
    }
}
[60, 80, 70]

进程已结束,退出代码0

9.keySet()
获取Map集合所有的键(key)
代码如下

  public static void main(String[] args) {
        Map<String,String> sqb = new HashMap<String,String>();
        sqb.put("Tom", "60");//添加数据
        sqb.put("Kate", "80");
        sqb.put("Jim","70");
        System.out.println(sqb.keySet());
    }

输出结果:

[Tom, Kate, Jim]

进程已结束,退出代码0

HashMap、TreeMap、HashTable区别

一:HashMap
线程不同步
允许 key 和 Vale 是 null,但是只允许一个 key 为 null,且这个元素存放在哈希表 0 角标位置
二:HashTable
同步
不允许key、value 是 null
TreeMap
线程不同步
value允许为null。
当未实现 Comparator 接口时,key 不可以为null
当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛 NullPointerException 异常。如果针对null情况实现了,可以存入,但是却不能正常使用get()访问,只能通过遍历去访问。

5丶Iterator接口

Iterator接口是用于遍历集合元素的接口。我们一般叫他迭代器,一般遍历集合有两种方式,迭代器是其中一种,另一种是增强for;
这个接口里面有三个方法
1: hasNext() 如果仍有元素可以迭代,则返回true。
2: next() 返回迭代的下一个元素。
3: remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
也就说,只要通过该接口就可以取出Collection集合中的元素进行操作,至于每一个具体的容器依据自己的数据结构,如何实现的具体取出细节,这个不用关心,这样就降低了取出元素和具体集合的耦合性,
我们来看如何遍历,代码如下:

List<String> list1 = new ArrayList<>();
    list1.add("a1");
    list1.add("a2");
    list1.add("a3");

    // while循环方式遍历
    Iterator it1 = list1.iterator();
    while (it1.hasNext()) {
        System.out.println(it1.next());
    }

    // for循环方式遍历
    for (Iterator it2 = list1.iterator(); it2.hasNext(); ) {
        System.out.println(it2.next());
    }

使用Iterator迭代器进行删除集合元素,则不会出现并发修改异常。

三丶集合工具类Collections

这个类主要是为了方便对集合的操作。这个类不需要创建对象,内部提供的都是静态方法。

Collections.sort(list);//list集合进行元素的自然顺序排序。
Collections.sort(list,new ComparatorByLen());//按指定的比较器方法排序。
class ComparatorByLen implements Comparator<String>{
  public int compare(String s1,String s2){
     int temp = s1.length()-s2.length();
     return temp==0?s1.compareTo(s2):temp;
  }
}
Collections.max(list);//返回list中字典顺序最大的元素。
int index = Collections.binarySearch(list,"zz");//二分查找,返回角标。
Collections.reverseOrder();//逆向反转排序。
Collections.shuffle(list);//随机对list中的元素进行位置的置换。

集合的选用

各种集合的特点已经总结出来了,我们在使用的时候,主要根据集合的特点来选用,比如我们需要根据键值获取到元素值时就选用Map接口下的集合,需要排序时选择TreeMap,不需要排序时就选择HashMap,需要保证线程安全就选用ConcurrentHashMap.当我们只需要存放元素值时,就选择实现Collection接口的集合,需要保证元素唯一时选择实现Set接口的集合比如TreeSet或HashSet,不需要就选择实现List接口的比如ArrayList或LinkedList,然后再根据实现这些接口的集合的特点来选用。

总结

总结到这里,但是我绝对各种集合的特点还是要经常复习,这样才能在以后根据需要选出最合适的集合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值