读取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来实现压缩。