Java中的一些基础代码片段_2


=Start=

缘由:

在学习Java的过程中不断用文章进行整理总结(常用功能的Java实现),争取早日能较为熟练的使用Java进行开发。

正文:

参考解答:
1. Java中如何将 Long 型转换成 int/Integer 型

Java中Integer属于不可更改类型,而且Long和Integer没有任何继承关系,所以不能直接转换。否则会报错「java.lang.Long cannot be cast to java.lang.Integer」

注:java.lang.Number 是 Integer,Long 的父类。

// 简单类型的转换可以直接进行
long l = 100000;
int i = (int) l;

// Long型变量的转换就不能直接进行了
Long x = 100L;
int y = x.intValue();
2. Java中字符串的常用操作
// 字符查找 & 字符串查找
str.indexOf()

// 字符串截取
str.substring()

// 字符串切分
str.split()

当对字符串进行修改的操作较多的时候,需要使用 StringBuffer 和 StringBuilder 类。因为和常规的 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

3. 特殊一点的字符串切分

借助:
import com.google.common.base.Splitter;
实现 在切分时,自动去掉空值 的功能。

package com.ixyzero.learn.misc;

import com.google.common.base.Splitter;

import java.util.List;

public class TestStringUtils {
    public static void main(String[] args) {
        String testInput = "1,2,,4,,6";
        String[] arrResult = testInput.split(","); // [1, 2, '', 4, '', 6]
        System.out.println(arrResult.length); // 6
        for (int i=0; i<arrResult.length; i++) {
            System.out.println(Integer.valueOf(i) + "]=>\t" + arrResult[i]);
        }
        System.out.println();

        Splitter splitter = Splitter.on(",").trimResults();
        List<String> valueList = null;
        valueList = splitter.omitEmptyStrings().splitToList(testInput);
        System.out.println(valueList);	// [1, 2, 4, 6]
        System.out.println(valueList.size());	// 4
        for (int i=0; i<valueList.size(); i++) {
            System.out.println(Integer.valueOf(i) + "]=>\t" + valueList.get(i));
        }
    }
}
4. Java中日期字符串格式的校验
package com.ixyzero.learn.misc;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestValidDateStr {
    public static boolean isValidDate(String s, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        if(s == null || s.trim().equals("") || pattern == null || pattern.trim().equals("")){
            return false;
        }
        try {
            return sdf.format(sdf.parse(s)).equals(s);
        } catch (Exception e) {
            return false;
        }
    }

    public static void main(String[] args) {
        System.out.println(isValidDate("", "yyyy-MM")); // false
        System.out.println(isValidDate("2018-06", "yyyy-MM"));  // true
        System.out.println(isValidDate("2018-06-09", "yyyy-MM"));   // false
        System.out.println(isValidDate("2018-06-09", ""));   // false
        System.out.println(isValidDate("2018-06-09 11:01", "yyyy-MM-dd HH:mm"));   // true

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        System.out.println(sdf.format(new Date()));
    }

}
5. Java中打印 数组 的3种方法总结
package com.ixyzero.learn.misc;

public class TestArray {
    public static void main(String[] args) {
        double[] myList = {1.9, 2.9, 3.4, 3.5};

        // 打印所有数组元素(常规 for 循环——根据数组下标进行遍历)
        for (int i = 0; i < myList.length; i++) {
           System.out.println(myList[i]);
        }

        // 打印所有数组元素(foreach 循环)
        for (double element: myList) {
           System.out.println(element);
        }

        /**
         * 使用 Arrays.toString 输出数组内容
         */
        System.out.println(Arrays.toString(myList));
    }
}
6. Java中打印 map 的方法总结
package com.ixyzero.learn.misc;

import java.util.*;
import java.util.Map.Entry;

/**
 * https://stackoverflow.com/questions/8119366/sorting-hashmap-by-values/13913206#13913206
 */
public class TestPrintMap
{
    public static void main(String[] args) {

        // Creating dummy unsorted map
        Map<String, Integer> unsortedMap = new HashMap<>();
        unsortedMap.put("B", 55);
        unsortedMap.put("A", 80);
        unsortedMap.put("D", 20);
        unsortedMap.put("C", 70);

        System.out.println("Before sorting......");
        printMap(unsortedMap);
    }

    public static void printMap(Map<String, Integer> map)
    {
        for (Entry<String, Integer> entry : map.entrySet()) {
            System.out.println("Key: " + entry.getKey() + "\tValue: "+ entry.getValue());
        }
    }
}

&

import java.util.*;

public class TestPrint {
    public static void main(String[] args) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("1", "value1");
    map.put("2", "value2");
    map.put("3", "value3");

    //第一种:普遍使用,二次取值
    System.out.println("通过Map.keySet遍历key和value:");
    for (String key : map.keySet()) {
      System.out.println("key= "+ key + " and value= " + map.get(key));
    }

    //第二种
    System.out.println("通过Map.entrySet使用iterator遍历key和value:");
    Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry<String, String> entry = it.next();
      System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
    }

    //第三种:推荐,尤其是容量大时
    System.out.println("通过Map.entrySet遍历key和value");
    for (Map.Entry<String, String> entry : map.entrySet()) {
      System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
    }

    //第四种
    System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
    for (String v : map.values()) {
      System.out.println("value= " + v);
    }

}

除了这种指定Map类型的方式之外,还可以考虑借助一下泛型(在map元素不是特别多的情况下)来实现。

参考链接:
  • 如上

=END=

,

《 “Java中的一些基础代码片段_2” 》 有 13 条评论

  1. Java执行系统命令的方法和原理
    https://xz.aliyun.com/t/2342
    http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
    http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/Process.html
    `
    要构建JSP命令执行后门,首先需要了解Java语言执行系统命令的方法及其原理。通过查阅资料知道:目前Java语言执行系统命令主要通过下面两个类的相关方法实现:
    java.lang.Runtime
    java.lang.ProcessBuilder

    查阅 Java 文档 可以发现,上面两个类,都是对java.lang.Process抽象类的实现。

    Java语言中执行系统命令的方式,简单来说就是由JVM创建一个本机进程,加载对应的指令到进程的地址空间中,然后执行该指令。
    而java.lang.Runtime.getRuntime().exec()和 java.lang.ProcessBuilder.start()方法,其实就是创建一个进程的方法。

    总结一下,Java语言执行系统命令相关类和方法的调用关系表示如下图:
    java.lang.Runtime
    —> getRuntime().exec()
    java.lang.ProcessBuilder
    —> start()
    java.lang.ProcessImpl.start()
    `

  2. rsyslog在打日志的时候,在日期那儿一般是「不会」补零,而是用「空格」替代;所以如果你的程序写的不够健壮,可能会在某个月的前几天出现异常,过了这段期间又自动恢复,没有遇到过这个问题的处理起来还真的是挺麻烦的。
    `
    /**
    * 下面的几点问题在于:
    * ‘Jul 2’
    * ‘Jun 14′
    * 日志里面把本来以为的 ’02’ 用 ‘ 2’ 来写,所以常规的 split() 切分时会多出来一个元素,从而导致匹配失败;
    * 用 Splitter 可以解决切分的问题,但是,切出来的结果是 List 的,而不是之前的 String[] 数组,有一定区别,但区别不大。
    */
    String record = “2018-07-02T11:36:42.146Z 172.16.9.15 Jul 2 19:36:40 hostname01 sshd[25882]: Accepted password for root from 172.16.9.49 port 40675 ssh2″;
    String split_record[] = record.split(” “);
    System.out.println(split_record.length); // 17

    String record2 = “2018-07-02T11:36:42.146Z 172.16.9.15 Jul 2 19:36:40 hostname01 sshd[25882]: Accepted password for root from 172.16.9.49 port 40675 ssh2″;
    Splitter splitter = Splitter.on(” “).trimResults();
    List split_record2 = splitter.omitEmptyStrings().splitToList(record2);
    System.out.println(split_record2.size()); // 16

    String record3 = “2018-06-14T07:47:45.460Z 192.168.16.5 Jun 14 15:47:41 hostname02 sshd[4754]: Accepted password for root from 111.33.10.152 port 26779 ssh2”;
    List split_record3 = splitter.omitEmptyStrings().splitToList(record3);
    System.out.println(split_record3.size()); // 16
    `

  3. Java中的字符串替换
    https://stackoverflow.com/questions/2360231/how-do-you-replace-double-quotes-with-a-blank-space-in-java
    https://stackoverflow.com/questions/13209866/java-replace-method-replacing-with-empty-character
    `
    1、单个字符
    String Str = new String(“hello”);
    System.out.print(Str);
    System.out.println(Str.replace(‘o’, ‘T’)); // 单个字符的替换,用「单引号」括起来

    2、字符串
    System.out.println(“I don’t like these \”double\” quotes”.replace(“\””, “”));
    // 使用「双引号」括起来
    `

    • Java中字符串比较时的一些注意事项:
      1、先判断是否为 null 避免空指针异常;
      2、再判断是否 equal 进行内容比较;
      `
      String foo = null;
      String bar = “Some string”;

      if (foo != null && foo.equals(bar)) {
      // Do something here.
      }

      // 或
      if (StringUtils.equals(foo, bar)) {
      // Do something here.
      }
      `

  4. Java 8中字符串拼接新姿势:StringJoiner
    https://mp.weixin.qq.com/s/P9QGM-7IXAcWviSopK_-Hw
    `
    本文介绍了Java 8中提供的可变字符串类——StringJoiner,可以用于字符串拼接。

    StringJoiner其实是通过StringBuilder实现的,所以他的性能和StringBuilder差不多,他也是非线程安全的。

    如果日常开发中中,需要进行字符串拼接,如何选择?
    1、如果只是简单的字符串拼接,考虑直接使用”+”即可。
    2、如果是在for循环中进行字符串拼接,考虑使用StringBuilder和StringBuffer。
    3、如果是通过一个集合(如List)进行字符串拼接,则考虑使用StringJoiner。
    4、如果是对一组数据进行拼接,则可以考虑将其转换成Stream,并使用StringJoiner处理。
    `
    为什么阿里巴巴不建议在for循环中使用”+”进行字符串拼接
    https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650123039&idx=1&sn=a3aa2348f7ed0c9d5014ba66737285b4

  5. Java中如何进行高效的字符串拼接?
    https://stackoverflow.com/questions/47605/string-concatenation-concat-vs-operator
    `
    String a = b + c + d;
    //等价于
    String a = new StringBuilder(b).append(c).append(d).toString();

    使用建议优先级排序:
    StringBuilder(非线程安全) / StringBuffer(线程安全)
    concat
    a += b
    `
    StringBuffer和StringBuilder的区别
    https://blog.csdn.net/mad1989/article/details/26389541
    `
    String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。

    如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;如果要保证线程安全,自然是StringBuffer。
    `

  6. java string split 的用法
    https://stackoverflow.com/questions/24701197/java-string-split-method-zero-and-negative-limit

    java split函数的几个问题
    https://www.cnblogs.com/xuxm2007/archive/2011/10/12/2208123.html
    `
    首先输入的regex是一个正则表达式,而不是一个普通的字符串,所以导致很多在正则表达式里面有特殊意义的比如 “.” “|” “\” ,如果直接使用是不行的,另外一个方面我们输入的regex是以字符串形式传递的,对有些字符必须要转义,尤其是”\”,下面请看例子

    String[] aa = “aaa|bbb|ccc”.split(“|”); //wrong
    String[] aa = “aaa|bbb|ccc”.split(“\\|”); //right
    `

    https://www.runoob.com/java/java-string-split.html
    `
    split() 方法根据匹配给定的正则表达式来拆分字符串。

    注意: . 、 | 和 * 等转义字符,必须得加 \\。
    注意:多个分隔符,可以用 | 作为连字符。

    语法
    public String[] split(String regex, int limit)

    参数
    regex — 正则表达式分隔符。
    limit — 分割的份数。

    返回值
    字符串数组。
    `

  7. java中因为 int 和 Integer 不同导致的 NPE 问题
    https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it
    https://blog.csdn.net/weixin_41575100/article/details/78953079
    `
    int 是基本类型,不是类,为了符合面向对象编程,后来出现了Integer类,它是对int进行封装的。
    int 不是对象,是java原始的数据类型,它默认值为0。
    Integer 是对象,它有自己的方法,默认值为NULL。

    建议在用 Integer 时,注意检查其值是否为 null ,避免 NPE 报错。
    `

  8. 你只会用 split?试试 StringTokenizer,性能可以快 4 倍!!
    https://mp.weixin.qq.com/s/Ai8vHCQejIB5P1ipH55QDQ
    `
    我们都知道,分割字符串要使用 String 的 split() 方法,split 方法虽然深入人心,使用也简单,但效率太低!

    其实在 JDK 中,还有一个性能很强的纯字符串分割工具类:StringTokenizer。

    StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
    StringTokenizer 原来是一个遗留类,并未被废弃,只是出于兼容性原因而被保留,在新代码中已经不鼓励使用它了,建议使用 String 的 split 方法或 java.util.regex 包代替。

    We split the input line into string tokens, since one line may contain multiple values. To split the input, StringTokenizer is 4X faster than string.split().

    # 总结
    虽然 JDK 不鼓励使用 StringTokenizer 了,但并不说明它不能用了,相反,如果你的系统对性能有非常严格的要求,又不是很复杂的字符串分割,好好使用它反而可以带来高效。

    但话又说回来,一般的应用程序用 split 也就够了,因为它够简单、又支持正则表达式,在一般的应用中也不会存在像文中测试的大批量的字符串循环分割,另外,StringTokenizer 在单次分割的性能上也没有性能优势。

    最后,关于字符串的分割方法,我们除了字符串本身的 split 方法,我们还要知道 StringTokenizer 这个类,多知道点不是坏事。另外,在 Spring、Apache Commons 工具类中也都有封装好的 StringTokenizer 工具类,有兴趣的可以直接拿去用。
    `
    https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/StringTokenizer.html
    https://www.cpe.ku.ac.th/~jim/java-io.html

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注