zoukankan      html  css  js  c++  java
  • 狂神说Java个人笔记-API,集合, IO

    常用API

    date

        // System.exit(0);//强制退出java程序非0是异常结束
           //long l = System.currentTimeMillis();//返回当前时间与1970年子午夜交替毫秒值
    //       Date date = new Date();//返回具体日期时间
    //       DateFormat dateInstance = DateFormat.getDateInstance();//获取日期格式
    //       DateFormat dateTimeInstance = DateFormat.getDateTimeInstance();//获取具体日期时间
    //       String s = dateInstance.format(date);
    //       String s1 = dateTimeInstance.format(date);
    //       System.out.println(s);
    //       System.out.println(s1);
           String s="2020/4/4 22:22:22";
           //编写对应日期格式,将字符串日期转换为日期格式
           SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
           Date parse = simpleDateFormat.parse(s);
           System.out.println(parse);

     

    math

    int abs = Math.abs(-5);
    Math.sqrt(1000.0);
    Math.max(1000,2000);
    Math.min(1000,2000);
    Math.round(1000.6f);
    Math.random();
    Random random = new Random();
    int i = random.nextInt(100);
    System.out.println(i);

     

    BigInteger类

    BigInteger b1 = new BigInteger("6666666666");
    BigInteger b2 = new BigInteger("2222222222");
    //加、减、乘、除、取模
    System.out.println(b1.add(b2));
    System.out.println(b1.subtract(b2));
    System.out.println(b1.multiply(b2));
    System.out.println(b1.divide(b2));
    System.out.println(b1.remainder(b2));

    BigDecimal类

    BigDecimal b3 = new BigDecimal("15.3");
    BigDecimal b4 = new BigDecimal("3.0");
    System.out.println(b3.divide(b4,5,BigDecimal.ROUND_HALF_UP));
    //除法除不尽可以在后面加,保留几位小数 ,属性(四舍五入)

    克隆技术

    类要实现克隆,需要做两步:

    1. 实现Cloneable接口;

    2. 重写Object的clone方法。

      Timer定时器

      Timer timer = new Timer();
      TimerTask task = new TimerTask() {

         public void run() {
             System.out.println("定时任务被执行了");
        }
      };
      //一段时间后执行定时任务
      timer.schedule(task,2000);
      //在具体时间执行任务
      timer.schedule(task,new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/5/18 14:56:10"));
      //在一段时间后执行任务,并且每隔多久执行一次
      timer.schedule(task,2000,3000);

      Calendar

      常用成员方法

      public int get(int field):返回给定日历字段的值。
      public void set(int field,int value):将给定日历字段设置给定值。
      public abstract void add(int field,int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
      public Date getTime();把日历时间值转换为date对象

       

      String

      String:字符串,使用一对“”引起来表示

      1. String声明为final的,不可被继承

      2. String实现了Serializable接口:表示字符串是支持序列化的

      3. 实现了comparable接口:表示String可以比较大小

      4. String内部定义了final char【】 value用于存储字符串数据

      5. String:代表不可变的字符序列:简称:不可变性。

        体现:当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值

      6. 通过字面量的方式给一个字符串赋值,此时的字符串值声明在字符串常量池中,字符串常量池中是不会存储相同内容的字符串。

        基本类型与字符串之间的转换

        基本类型--》字符串

        1.基本类型—+“”,

        2.包装类的静态方法tostring(参数),不是Object的toString重载,static String toString(int i)返回一个指定整数的String对象

        3.String类的静态方法valueof(参数)

        字符串-》基本类型

        使用包装类大家平台方法parsexxx(“数值类型的字符串”)

        //基本类型转换字符串
        Integer i=1;
        String s=i+"";
        String s1=Integer.toString(1);
        System.out.println(i.toString());
        System.out.println(s1+200);
        String s2=String.valueOf(i);
        //字符串转换基本类型
        int i1=Integer.parseInt(s1);
        //字符串的操作
                   String s="猫猫猫狗猫猫猫猫猫猫狗猫猫猫猫猫狗猫猫猫猫猫猫猫";
                   //字符串检索
                   //检索字符串是否有该字符,返回Boolean
                   System.out.println(s.contains("狗"));//有返回true
                   //检索字符串是否存在,存在返回位置下标,不存在返回-1
                   System.out.println(s.indexOf("狗"));//存在返回位置下标
                   //检索字符串开始位置是否为该字符
                   System.out.println(s.startsWith("猫"));//返回Boolean
                   //检索字符串结尾位置是否为该字符
                   System.out.println(s.endsWith("猫"));//返回Boolean

                   //字符串替换
                   System.out.println(s.replace("狗","鼠"));
                   //字符串拆分以该字符拆分并输出0下标的字符
                   System.out.println(s.split("狗")[0]);
                   //字符的长度
                   System.out.println(s.length());
                   //字符是否为空
                   System.out.println(s.isEmpty());
                   

        StringBuilder

        StringBuilder su=new StringBuilder();
        String s=su.toString();

        集合

        image-20200519152612018

         

         

    重点:HashMap

    ①HashMap的工作原理

    HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。

    当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。

    ②HashMap和Hashtable的区别

    HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

    1. HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。

    2. HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

    3. 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

    4. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

    5. HashMap不能保证随着时间的推移Map中的元素次序是不变的。

    要注意的一些重要术语:

    1) sychronized意味着在一次仅有一个线程能够更改Hashtable。就是说任何线程要更新Hashtable时要首先获得同步锁,其它线程要等到同步锁被释放之后才能再次获得同步锁更新Hashtable。

    2) Fail-safe和iterator迭代器相关。如果某个集合对象创建了Iterator或者ListIterator,然后其它的线程试图“结构上”更改集合对象,将会抛出ConcurrentModificationException异常。但其它线程可以通过set()方法更改集合对象是允许的,因为这并没有从“结构上”更改集合。但是假如已经从结构上进行了更改,再调用set()方法,将会抛出IllegalArgumentException异常。

    3) 结构上的更改指的是删除或者插入一个元素,这样会影响到map的结构。

    我们能否让HashMap同步?

    HashMap可以通过下面的语句进行同步: Map m = Collections.synchronizeMap(hashMap);

    结论

    Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。

    ashMap和HashSet的区别是Java面试中最常被问到的问题。如果没有涉及到Collection框架以及多线程的面试,可以说是不完整。而Collection框架的问题不涉及到HashSet和HashMap,也可以说是不完整。HashMap和HashSet都是collection框架的一部分,它们让我们能够使用对象的集合。collection框架有自己的接口和实现,主要分为Set接口,List接口和Queue接口。它们有各自的特点,Set的集合里不允许对象有重复的值,List允许有重复,它对集合中的对象进行索引,Queue的工作原理是FCFS算法(First Come, First Serve)。

    首先让我们来看看什么是HashMap和HashSet,然后再来比较它们之间的分别。

    ③HashMap和HashSet的区别

    HashMap和HashSet的区别是Java面试中最常被问到的问题。如果没有涉及到Collection框架以及多线程的面试,可以说是不完整。而Collection框架的问题不涉及到HashSet和HashMap,也可以说是不完整。HashMap和HashSet都是collection框架的一部分,它们让我们能够使用对象的集合。collection框架有自己的接口和实现,主要分为Set接口,List接口和Queue接口。它们有各自的特点,Set的集合里不允许对象有重复的值,List允许有重复,它对集合中的对象进行索引,Queue的工作原理是FCFS算法(First Come, First Serve)。

    首先让我们来看看什么是HashMap和HashSet,然后再来比较它们之间的分别。

    什么是HashSet

    HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。

    public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true。

    什么是HashMap

    HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许重复的键。Map接口有两个基本的实现,HashMap和TreeMap。TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null。HashMap是非synchronized的,但collection框架提供方法能保证HashMap synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。

    public Object put(Object Key,Object value)方法用来将元素添加到map中。

    HashSet和HashMap的区别

    HashMapHashSet
    HashMap实现了Map接口 HashSet实现了Set接口
    HashMap储存键值对 HashSet仅仅存储对象
    使用put()方法将元素放入map中 使用add()方法将元素放入set中
    HashMap中使用键对象来计算hashcode值 HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
    HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢

     

     

    ④面试题

    HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此特殊呢?是因为这道题考察的深度很深。这题经常出现在高级或中高级面试中。投资银行更喜欢问这个问题,甚至会要求你实现HashMap来考察你的编程能力。ConcurrentHashMap和其它同步集合的引入让这道题变得更加复杂。让我们开始探索的旅程吧!

    “你用过HashMap吗?” “什么是HashMap?你为什么用到它?”

    几乎每个人都会回答“是的”,然后回答HashMap的一些特性,譬如HashMap可以接受null键值和值,而Hashtable则不能;HashMap是非synchronized;HashMap很快;以及HashMap储存的是键值对等等。这显示出你已经用过HashMap,而且对它相当的熟悉。但是面试官来个急转直下,从此刻开始问出一些刁钻的问题,关于HashMap的更多基础的细节。面试官可能会问出下面的问题:

    “你知道HashMap的工作原理吗?” “你知道HashMap的get()方法的工作原理吗?”

    你也许会回答“我没有详查标准的Java API,你可以看看Java源代码或者Open JDK。”“我可以用Google找到答案。”

    但一些面试者可能可以给出答案,“HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。”这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry。这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在bucket中存储值的话,你将不会回答如何从HashMap中获取对象的逻辑。这个答案相当的正确,也显示出面试者确实知道hashing以及HashMap的工作原理。但是这仅仅是故事的开始,当面试官加入一些Java程序员每天要碰到的实际场景的时候,错误的答案频现。下个问题可能是关于HashMap中的碰撞探测(collision detection)以及碰撞的解决方法:

    “当两个对象的hashcode相同会发生什么?” 从这里开始,真正的困惑开始了,一些面试者会回答因为hashcode相同,所以两个对象是相等的,HashMap将会抛出异常,或者不会存储它们。然后面试官可能会提醒他们有equals()和hashCode()两个方法,并告诉他们两个对象就算hashcode相同,但是它们可能并不相等。一些面试者可能就此放弃,而另外一些还能继续挺进,他们回答“因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。”这个答案非常的合理,虽然有很多种处理碰撞的方法,这种方法是最简单的,也正是HashMap的处理方法。但故事还没有完结,面试官会继续问:

    “如果两个键的hashcode相同,你如何获取值对象?” 面试者会回答:当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。面试官提醒他如果有两个值对象储存在同一个bucket,他给出答案:将会遍历链表直到找到值对象。面试官会问因为你并没有值对象去比较,你是如何确定确定找到值对象的?除非面试者直到HashMap在链表中存储的是键值对,否则他们不可能回答出这一题。

    其中一些记得这个重要知识点的面试者会说,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。完美的答案!

    许多情况下,面试者会在这个环节中出错,因为他们混淆了hashCode()和equals()方法。因为在此之前hashCode()屡屡出现,而equals()方法仅仅在获取值对象的时候才出现。一些优秀的开发者会指出使用不可变的、声明作final的对象,并且采用合适的equals()和hashCode()方法的话,将会减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用String,Interger这样的wrapper类作为键是非常好的选择。

    如果你认为到这里已经完结了,那么听到下面这个问题的时候,你会大吃一惊。“如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?”除非你真正知道HashMap的工作原理,否则你将回答不出这道题。默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。

    如果你能够回答这道问题,下面的问题来了:“你了解重新调整HashMap大小存在什么问题吗?”你可能回答不上来,这时面试官会提醒你当多线程的情况下,可能产生条件竞争(race condition)。

    当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。这个时候,你可以质问面试官,为什么这么奇怪,要在多线程的环境下使用HashMap呢?:)

    热心的读者贡献了更多的关于HashMap的问题:

      1. 为什么String, Interger这样的wrapper类适合作为键? String, Interger这样的wrapper类作为HashMap的键是再适合不过了,而且String最为常用。因为String是不可变的,也是final的,而且已经重写了equals()和hashCode()方法了。其他的wrapper类也有这个特点。不可变性是必要的,因为为了要计算hashCode(),就要防止键值改变,如果键值在放入时和获取时返回不同的hashcode的话,那么就不能从HashMap中找到你想要的对象。不可变性还有其他的优点如线程安全。如果你可以仅仅通过将某个field声明成final就能保证hashCode是不变的,那么请这么做吧。因为获取对象的时候要用到equals()和hashCode()方法,那么键对象正确的重写这两个方法是非常重要的。如果两个不相等的对象返回不同的hashcode的话,那么碰撞的几率就会小些,这样就能提高HashMap的性能。

      2. 我们可以使用自定义的对象作为键吗? 这是前一个问题的延伸。当然你可能使用任何对象作为键,只要它遵守了equals()和hashCode()方法的定义规则,并且当对象插入到Map中之后将不会再改变了。如果这个自定义对象时不可变的,那么它已经满足了作为键的条件,因为当它创建之后就已经不能改变了。

      3. 我们可以使用CocurrentHashMap来代替Hashtable吗?这是另外一个很热门的面试题,因为ConcurrentHashMap越来越多人用了。我们知道Hashtable是synchronized的,但是ConcurrentHashMap同步性能更好,因为它仅仅根据同步级别对map的一部分进行上锁。ConcurrentHashMap当然可以代替HashTable,但是HashTable提供更强的线程安全性。看看这篇博客查看Hashtable和ConcurrentHashMap的区别。

    IO流

    image-20200520104215113

    文件操作

    File file =new File("C:\Users\A450\Desktop\bbb");
     //file.createNewFile();//创建一个文件,File写具体目录到创建的文件名
     file.mkdir();//创建一个目录
     System.out.println(file.exists());//判断是否存在
     System.out.println(file.isFile());//判断是否为一个文件
     System.out.println(file.isDirectory());//判断是否为一个目录
     System.out.println(Arrays.toString(file.list()));//获取目录里的文件名以数组方式打印
    // file.delete();//删除文件
     file.renameTo(new File("C:\Users\A450\Desktop\ccc"));//改名字
    

     

    字节输入流

    //字节输入流FileInputStream
    public static void main(String[] args) throws IOException {
        File file = new File("C:\Users\A450\Desktop\aaa\1.txt");
        FileInputStream fis=null;
        try {
           fis= new FileInputStream(file);//
            System.out.println(fis.available());//读取文件长度
            System.out.println(fis.read());//读取文件并返回位置如果读取完返回-1
            byte[] b=new byte[1024];//准备一个byte数组放入读取文件
            int len = fis.read(b);//读取内容放入数组
            while(len!=-1){
                String s=new String(b);//将byte转换字符串
                System.out.println(s);//输出读到的字符串
                len = fis.read(b);
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            fis.close();
            
        }
    
    }

    FileOutputStream

    //字符输出流FileOutputStream
    public static void main(String[] args) {
        String s="你好,世界!";
        FileOutputStream fos=null;
        try {
            //写入文件,name:文件路径append:默认写入是覆盖写入;有true为追加写入
            fos=new FileOutputStream("C:\Users\A450\Desktop\aaa\2.txt",true);
            byte[] b=s.getBytes();//将写入的文件转换为字节数组
            fos.write(b,0,b.length);//写入文件,从0开始,到写入的长度
            fos.flush();//清空缓冲区,强制写入缓冲区文件
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            fos.close();
        }
    }

    FileReader

    //FileReader字符输入流
    public static void main(String[] args) throws IOException {
        File file=new File("C:\Users\A450\Desktop\aaa\1.txt");
        FileReader fr=null;
        try {
             fr=new FileReader(file);
             char[] c=new char[1024];//用字符保存读入的数据
            int len = fr.read();
            while (len!=-1){
                String s=new String(c);
                System.out.println(s);
                len=fr.read();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            fr.close();
        }
    }

    FileWriter

         //FileWriter字节输出流
        public static void main(String[] args) throws IOException {
            String s="你好!世界ssss";
            FileWriter fw=null;
            try {
                fw=new FileWriter("C:\Users\A450\Desktop\aaa\2.txt",true);
                fw.write(s);
                fw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                fw.close();
            
        }
    }

    BufferReader&BufferWriter

    缓冲流

    //缓冲流BufferedReader BufferedWriter
    public static void main(String[] args) throws IOException {
        File file=new File("C:\Users\A450\Desktop\aaa\1.txt");
        BufferedReader br=null;
        BufferedWriter bw=null;
        try {
            br= new BufferedReader(new FileReader(file));
            bw=new BufferedWriter(new FileWriter("C:\Users\A450\Desktop\aaa\2.txt"));
            String s=br.readLine();//逐行读取
            while (s!=null){
                System.out.println(s);
                bw.write(s+"
    ");
                bw.flush();
               s= br.readLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            br.close();
            bw.close();
        }
    }

    FileWriter

    //打印流
    public static void main(String[] args) {
        PrintWriter pw=null;
        try {
            pw=new PrintWriter(new FileWriter("C:\Users\A450\Desktop\aaa\2.txt"),true);
            pw.print("hello world");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            pw.close();
            
        }
    
    }

    ObjectOutputStream

    //对象输入流 调用的学生类必须引用接口Serializable
    public static void main(String[] args) throws IOException {
       Student stu1=new Student("赵东",11);
       Student stu2=new Student("赵2",12);
       Student stu3=new Student("赵3",13);
       Student stu4=new Student("赵4",14);
       ArrayList<Student> al=new ArrayList<Student>();
       al.add(stu1);
       al.add(stu2);
       al.add(stu3);
       al.add(stu4);
       ObjectOutputStream oos=null;
       try {
           oos=new ObjectOutputStream(new FileOutputStream("C:\Users\A450\Desktop\aaa\3.txt"));
           oos.writeObject(al);
           oos.flush();
      } catch (IOException e) {
           e.printStackTrace();
      }finally {
           oos.close();

      }
    }

    ObjectInputStream

    //对象输入流ObjectInputStream
    public static void main(String[] args) {
       ObjectInputStream ois=null;
       try {
           ois=new ObjectInputStream(new FileInputStream("C:\Users\A450\Desktop\aaa\3.txt"));
           ArrayList<Student> al=(ArrayList<Student>)ois.readObject();
           for (Student student : al) {
               System.out.println("姓名"+student.name+"年龄"+student.age);
          }
      } catch (Exception e) {
           e.printStackTrace();
      }
    }

     

  • 相关阅读:
    Linux下安装FTP服务(Ubuntu)
    Ubuntu下无法使用Secure_CRT连接服务器
    Mysql 锁机制
    PHP提取HTML代码中img标签下src属性
    Mysql 隐式转换
    PHPExcel在TP下使用
    ThinkPHP同时操作多个数据库
    PHP 时间相关操作
    ThinkPHP输入验证和I方法使用
    ThinkPHP模板内使用U方法
  • 原文地址:https://www.cnblogs.com/fire-dong/p/13414699.html
Copyright © 2011-2022 走看看