java基础复习(17)--字符串,集合,I/O

读取properties 文件时出现乱码


如果properties文件里含有中文时不可以用ResourceBundle度取,需先对properties文件进行编码转换
在JDK中提供了native2ascii命令 他能够实现字符编码的转换。
假设message.properties 文件在目录WEB-INF/resource目录下
在命令行模式下进入WEB-INF/resource目录,然后执行如下命令
native2ascii –encoding utf-8 message.properties message_zh_CN.properties
参数-encoding表示要转换成的编码格式
执行以上命令以后将生成message_zh_CN.properties文件 现在就可以用ResourceBundle类进行读取了


mutual exclusion---互斥


Hashtable和HashMap都实现了Map接口。
Hashtable继承Dictionary类。

Properties prop = System.getProperties();
    Enumeration en = prop.propertyNames();
    while(en.hasMoreElements()){
        String key = (String)en.nextElement();
        System.out.println(key+"="+prop.getProperty(key));
    }

 

字符串
字符串是常量,他们的值在创建之后就不可以改变了。

String s = "abc";
String b = s;
s = s+"d";
System.out.println(b);//abc
System.out.println(s);//abcd

 

String h = new String("test");
String h1 = new String("test");
 

以上两句代码产生了三个 "test"字符串对象。两个位于堆里,一个位于字符串常量池中。

 

问题:

public static void main(String[] args) {
        String s = "abc";
        change(s);
        System.out.println(s);

        s = test(s);
        System.out.println(s);
    }

    static void change(String str) {
        str = "abcdefg";
    }

    static String test(String str) {
        str = "abcdefg";
        return str;
    }
 

打印输出:
abc
abcdefg


分析:
change方法:
切记,java中是值传递。在change方法中,str是在栈中的一个变量,它一开始和s指向的是同一
个string,即“abc”,在change方法中,str又指向了新的对象,这根本不关s的事。所以s指向的
仍然是“abc”

test方法:
s重新指向了字符串常量池中的另一个字符串,所以打印出“abcdefg”

String s = "abc";
s = s+'d';
System.out.println(s);//输出abcd
 

分析:string可以直接和char做+运算 。今天才知道。


正则表达式不能嵌套表达


摘自jdk doc
public final class Patternextends Objectimplements Serializable正则表达式的编译表示形式。 指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

因此,典型的调用顺序是

 Pattern p = Pattern.compile("a*b");
 Matcher m = p.matcher("aaaaab");
 boolean b = m.matches();
 

在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句

 boolean b = Pattern.matches("a*b", "aaaaab");//等效于上面的三个语句,尽管对于重复的匹配而言

 

它效率不高,因为它不允许重用已编译的模式
此类的实例是不可变的,可供多个并发线程安全使用 。Matcher 类的实例用于此目的则不安全。

习题:
从键盘输入字符串,回车后按单词反转

 

 Scanner sc = new Scanner(System.in);
        LinkedList<String> list = new LinkedList<String>();
        String str = sc.nextLine();
        String[] arr = str.split(" ");
        for(int i=arr.length-1;i>=0;i--)
            list.add(arr[i]);
        for(String s : list){
            System.out.print(s);
            System.out.print(" ");
 

给你一组字符串:iu2ier343dfjsd,让你编程输出里面的数字。

 Scanner sc = new Scanner(System.in);
        String str = sc.next();
        //System.out.println(str);
        Pattern p = Pattern.compile("(\\d)");
        Matcher m = p.matcher(str);
        while(m.find()){
             System.out.println(m.group(0));
        }

 

列出目录和文件:

public class PrintFiles {

    public static void main(String[] args) {
        int level = 0;
        print(new File("D:\\ipMsg"), 0);
    }

    public static void print(File f, int level) {
        if (f.isDirectory() == false) {
            printSpace(level);
            System.out.println("[文件]:" + f.getAbsolutePath());
        } else {
            File[] farr = f.listFiles();
            printSpace(level);
            System.out.println("[文件夹]:" + f.getAbsolutePath());
            for (File file : farr) {
                print(file, level + 1);
            }
        }
    }

    public static void printSpace(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("--");
        }
    }
}

 

HashSet探究

HashSet内部使用到了HashMap。
当你调用HashSet的add方法将对象添加到集合中去时,根据add的返回值判断添加是否成功。

实则是以下操作:

public boolean add(E e) {
             return map.put(e, PRESENT)==null;
//Present是一个私有静态不可变的成员变量,private static final Object PRESENT = new Object();
    }
 

继续查看,map的put方法是如何实现的:

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
 

分析:

hashMap的put方法,与集合中的Entry一一比较。先判读对象的hashcode是否相等,相等后再调用equals。

static int hash(int h) {    
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
 

上面这段代码不知用意何在,对于移位一直都感到头疼啊。有人研究出来的通知声哈。
然后后面的indexFor方法也很抽象呢。如何能保证取得索引的唯一性?


补充:
HashMap 是以数组的结构,用哈希函数值跟数组的长度做位与运算,获取对应数组的索引。浏览key值时,不保证顺序。


LinkedHashMap 是以双向列表的结构做实现的,浏览key值时候,可以保证顺序。

LinkedHashMap继承HashMap ,不同的是数据存储结构。


TreeMap 是以二叉树实现的Map接口。Map中的key值按照从小到大的顺序排列。key要实现comparable


同学问我一个问题,做个笔记哈:

Set<Object> set = new TreeSet<Object>();
set.add("dsaf");
set.add(“22”);
set.add(3);
System.out.println(set.toString());

 

分析:

编译没有问题,但是在执行到set.add(3);就出现了类型转换异常,因为TreeSet在加入对象时,会将该对象和已有对象进行比较,从而找 到该对象应该存放的位置。加入到该TreeSet中的对象应该实现Comparable接口的compareTo方法,会将新添加的对象和已有元素一一进 行比较,但是Integer的compareTo方法传进来的参数类型是Integer,但已有的却是String类型的实例,所以将string转换为 Integer当然出现了问题。


I/O流概述

 

概念:
1,为进行数据的输入/输出操作,java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表
述为“流”(stream)
2,Stream是从起源(source)到接收(sink)的有序数据
3,java.io包中定义了多个流类型(类和抽象类)来实现输入/输出功能
4,两种基本的流:输入流和输出流
--输入流:只能从中读取字节数据,而不能向其写出数据
--输出流:只能向其写入字节数据,而不能从中读取数据
5,按照流所处理的数据类型划分,可以分为:
字节流:用于处理字节数据
字符流:用于处理Unicode字符数据

节点流和处理流
处理流:实现对一个已存在的流的连接和封装 ,通过所封装的流的功能调用实现数据读写功能的流。处理流也被称为高级流。


flush(),立即刷新输出缓冲区

FileOutputStream的write(int b)的写入效果:
该方法是native的,无法看到源代码,应该是将int的低字节或高字节写到了文件中。经测试发现写入的是int的低8位。如128写入后十六进制表示为80,255写入后为FF,256写入后为00传进去的是int,但是写入的确是个字节,不过和read()方法倒是对称,读出的是个字节,但返回的却是int

特殊的文件输出流
RandomAccessFile是一种特殊的文件流,可以用它在文件的任何地方查找或者插入数据
同时实现了DataInput和DataOutput接口,所以可以用它来读写文件

压缩文件可以直接调用winrar来压缩,也可以利用已有的api来实现压缩。

你可能感兴趣的:(java,jdk,数据结构,编程,正则表达式)