Java CookBook(一)

Java字符串和正则表达式

String是固定不变的,即当你改变String时实际是上创建了一个新字符串,而原来的字符串保持不变。StringBufferStringBuilder允许内容是可变的,它们都提供setCharAt(),insert()等修改字符串内容的方法。StringBuffer是线程安全的,在多线程应用中必须使用StringBufferStringBuilder不是线程安全的,当不使用多线程时,使用StringBuilder更高效。

java正则表达式由MatcherPattern提供支持。更常用的是String的一些方法如split(),matches()都可以将正则表达式作为参数接收。

/**
 * Author: Orisun
 * Date: Sep 16, 2011
 * FileName: Regex.java
 * Function: 
 */
package Nine;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex {

	public static void main(String[] args){
		Pattern pat=Pattern.compile("\\b\\w+@XYZ\\.com\\b");
		Matcher mat=pat.matcher("Company Contact Info\n"+
				"Tom 555-1111 tom@XYZ.com\n"+
				"Marry 555-2222 Mary@XYZ.com\n"+
				"Don 555-3333 Don@XYZ.com");
		while(mat.find()){		//对find的每次调用都会从上一次停止的位置开始
			System.out.println("Match: "+mat.group());		//匹配的字符串在group中
		}
	}
}
/***********
输出:
Match: tom@XYZ.com
Match: Mary@XYZ.com
Match: Don@XYZ.com
***********/

正则表达式中除了使用或还可以使用与。[\w && [^A-Z]]匹配大写字母以外的所有单词字符。

+1次或多次

*0次或多次

0次或1

+*?都是贪婪量词,它们匹配最长的匹配序列。比如从”simple sample”中匹配模式”s.+e”,则将匹配”simple sample”。贪婪量词后加一个”?“成为胁迫量词,匹配最短的匹配序列,前面的例子”s.+?e”将匹配”simple“。贪婪量词后加一个”+“成为占有量词,匹配最短的匹配序列,不匹配较短的序列,即使它能使整个表达式匹配成功,”s.++e”会匹配失败,因为“.++”将匹配s之后的所有字符,模式是占有的,它不会释放最后的e

正则表达式中用()来分组,\1是第一个组,\2是第二个组

正则表达式前加”(?i)”则忽略大小写,”(?i)here”将匹配here,HereHERE。它也会匹配”there”,因为并没有要求所查找的”here”是一个单独的单词。如果要查找的是整个单词,则要加上词界限定”\b(?i)here\b”

Java文件处理

Java.util.zip.DeflaterOutputStream

void write(int byteval)

void close()

Java.util.zip.InflaterInputStream

int read()

void close()

以上方法不需要创建压缩文件或解压,而是直接使用标准压缩算法对数据压缩后写入文件,或直接从压缩文件中读出数据。当使用非常大的数据文件时,这是非常有用的。

java直接创建GZIP文件是简单的,只需要创建GZIPOutputStream,然后向它写入数据即可。创建ZIP会稍微复杂些。一般ZIP文件可以包含一个或多个压缩文件。

对象序列化:将对象写入文件存储之,同时可以读取并恢复这些对象。

因为某个对象可能包含其他对象的引用,因此对象的序列化可能涉及相当复杂的过程。为了将对象序列化它必须实现Serializable接口,这个接口没有定义成员,它只是一个标志。一个可序列化的类的子类都 是可序列化的。但是声明为transient的变量不被序列化工具保存。而且也不保存static变量。因此序列化只保存对象的当前状态。

ObjectOutputStream fout=new ObjectOutputStream(new FileOutputStream(“filename”));

fout.writeObject(obj1);

ObjectInputStream fin=new ObjectInputStream(new FileInputStream(“filename”));

MyClass obj2=(MyClass)fin.readObject();

格式化数据

Formatter fmt=new Formatter();

fmt.format(“Formatter is %s powerful %d %f”,”very”,88,3.14);

String str=fmt.toString();

%g%G—使用%e%f中较短的一个

%t%T—时间或日期

- 左对齐

0 0而不是用空格填补

%S 字符串大写

n$ n是所需变量的引用,从1开始

fmt.format(“%3$s %1$s %2$d”,”bat”,23,”gama”);

则输出gama 23 bat

fmt.format(“%s in uppercase is %1$S”,”Testing”);

则输出Testing in uppercase is TESTING

使用相对索引“<”允许你重复使用与前面的格式指定符匹配的变量,比如前一例子等价地可以用

fmt.format(“%s in uppercase is %<S”,”Testing”);

Array.fill(charArr,' '); 给一个数组统一赋值

获取当前的日期和时间有两种方式:

1.调用Calendar的静态工厂方法static Calendar getInstance();

2.创建Date对象的一个实例new Date()

通过调用getTimeInMillis()可以从Calendar获得日期和时间的长格式版本,或者调用getTime()Date获得日期和时间的长格式版本。

Formatter fmt=new Formatter();

Calendar cal=Calendar.getInstance();

fmt.format(Local.GERMAN,”For Local.GERMAN:%tc\n”,cal); 输出德国时间的标准格式

c 标准日期和时间的字符串,格式为:天 月份 日期 hh:mm:ss 年份

Formatter fmtConsole=new Formatter(System.out);

Formatter fmtFile=new Formatter(new FileOutputStream(“filename”));

printf的好处是创建时间戳,在创建日志文件时经常使用。

Static void timeStamp(String msg,PrintWriter pw){
Calendar cal=Calendar.getInstance();

pw.printf(“%s %tc\n”,msg,cal);

}

PrintWriter pw=new PrintWriter(new FileWriter(“filename”,true));

timeStamp(“File opened”,pw);

Java集合

java5之后所有的API都为了泛型而重新设计。现在志有的集合都是泛型的,并且集合上的操作都接收泛型参数。泛型通过增加类型安全而改进了集合,因为之前的集合都存储object对象,会导致运行时类型不匹配的错误。而使用泛型则显示地指定了数据类型。

利用自动拆装箱可以方便地在集合中存储简单数据类型(比如int是简单数据类型,而Integer就不是)。

上图是接口之间的扩展关系。所有的集合都实现Iterator接口,这意味着可以通过for-each风格的for循环进行遍历。

Collection中的方法:

int hashCode()

boolean retainAll(Collection <?> col) 删除调用集合中除col以外和所有元素

Object[] toArray

<T> T[] toArray( T array[])

List中允许包含重复对象。

ListIterator<E> listIterator() 返回一个失迭代器,指向列表的开始处

ListIterator<E> listIterator(int index) 返回一个失迭代器,指向列表的指定索引位置

Set不允许有重复元素。

SortedSet元素是升序的,从小到大。

Interface SortedSet <E>

E first() 返回第一个(最小的)元素

E last()

SortedSet<E> headSet(E end) 从头部获取小于end的元素

SortedSet<E> Set(E end)

SortedSet<E> subSet(E start,E end)

NavigableSetjava6中新增的,它扩展了SortedSet,基于给定一个值或几个值的最接近匹配。

E ceiling(E obj) 返回>=obj的最小元素

E floor(E obj)

E higher(E obj) 返回>obj的最小元素

E lower(E obj)

Iterator <E> descendingIterator() 返回从大到小移动的迭代器,即反向迭代器。

NavigableSet <E> descendingSet()

NavigableSet <E> headSet(E upperBound,boolean incl) incltrue时等价于ceiling,为false时等价于higher

NavigableSet <E> tailSet(E lowerBound,boolean incl)

NavigableSet <E> subSet(E lowerBound,boolean incl1,E upperBound,boolean incl2)

E pollFirst() 返回并删除第一个元素(亦即最小的元素)

E pollLast()

Deque扩展了Queue,声明双端队列的行为,它最重要的特性是push()pop(),这使得Deque能像堆栈一样工作。

Void addFirst(E obj)

void addLast(E obj)



上面讲完集合接口,下面讲集合类。



ArrayList实现动态数组,它以初始大小创建,当超过初始大小时,集合会自动增大;当删除对象时,集合会自动缩小。最好设定一个比较大的初始容量,这会防止后续的重新分配内存,因为分配是耗时的。

Void ensureCapacity(int cap)

void trimToSize()

有了ArrayListVector逐渐被废弃。

EnumSet用于enum元素。

Class EnumSet <E extends Enum<E>>

LinkedList实现了ListDeque接口。同时因为它采用了双链表结构,可以高效地插入、删除、逆序遍历。

HashSet的构造函数:

HashSet()

HashSet(Collection <? extends E> col)

HashSet(int capacity)

HashSet(int capacity,float fillRatio)

默认情况下填充率fillRatio0.75HashSet中的元素不会以任何特定的顺序排列,当用迭代器或for遍历时得到的顺序是未知的。

LinkedHashSetHashSet的基础之上又采用了双向链表结构,所以列表的顺序和插入的顺序是一致的,同时仍获得哈希化的快速查找的好处。(可以想像它牺牲了多少的空间代价!)

TreeSet中的元素是按升序排列的,同时采用了树结构,所以访问和返回元素非常快,这使得TreeSet对于快速访问大量的存储信息而言是极佳的选择,不过它不允许元素重复。

PriorityQueue创建区分优先权的队列,默认情况下优先权基于元素的自然顺序,但是在构造PriorityQueue时,可以通过指定一个比较器来改变这种顺序。

PriorityQueue(int capacity, Comparator<? Super E> comp)

映射不实现Collection接口,映射中的键和值都必须是对象,不能是基本数据类型。

映射不实现Iterable接口,因此不能用迭代器或for循环遍历,要想这么做需要先获得映射的集合视图。

Map接口 interface Map<K,V>

Boolean containsKey(Object k)

boolean containsValue(Object v)

SortedMap接口是按键的升序排列的。 Interface SortedMap<K,V>

Comparator <? super K> comparator() 返回调用的排序映射比较器。如果使用的是自然排序则返回null

K firstKey()

K lastKey()

SortedMap<K,V> headMap(K end) <end

SortedMap<K,V> tailMap(K start) >=start

SortedMap<K,V> subMap(K start ,K end) >=start<end

NavagableMap接口扩展了SortedMap,基于给定一个键或几个键最接近的匹配,类同于NavigableSetSortedSet的关系。

Map.Entry接口

boolean equals(Object obj)

K getKey()

V getValue()

int hashCode()

V setValue(V v)



常用的映射类有:

HashMap

TreeMap 采用树形结构,实现了NavigableMap

WeakHashMap 当键不再使用时,允许映射中元素的内存被回收

LinkedHashMap 采用双向链表,允许按插入顺序来迭代



ArrayList<Integer> col=new ArrayList<Integer>();

for(int x:col){}

一般集合可以是任意类型的对象,但对于基于排序的集合,比如PriorityQueueTreeSet它们的对象必须实现Comparable接口,该接口中定义了compareTo()方法,如果需要,还要重写equals()方法。

ListIterator接口扩展了Iterator接口,可以进行列表的双向遍历和元素的修改,因此ListIterator中有以下方法:

boolean hasPrevious()

E previous()

Collections中定义了以下算法:

static void reverse(List <?> col) 颠倒列表

static void rotate(List <?> col,int n) 把元素从列表的一端取走,移到另一端

static void shuffle(List <?> col) 随机化元素序列

static <T> int binarySearch(List <? extendsComparable<? Super T>> col,T val) 二分查找

sattic <T extends Comparable<? Super T>> void sort(List <T> col) 排序

当一个线程准备或可能修改一个集合,而另一个线程正好访问这个集合时,就要求同步集合。集合类都不是同步的,如果要创建同步集合,需要使用synchronized方法。

package Nine;

import java.util.Collection;
import java.util.Collections;
import java.util.TreeSet;

class MyThread implements Runnable{
	Thread t;
	Collection<String> col;
	MyThread(Collection<String> c){
		col=c;
		t=new Thread(this,"Second Thread");
		t.start();
	}
	public void run(){
		try{
			Thread.sleep(100);
			col.add("Omega");		//修改集合
			synchronized(col){	//进入临界资源区域,在离开区域之前,本线程独占资源col
				for(String str:col){
					System.out.println("Second Thread:"+str);	//读取集合
					Thread.sleep(500);
				}
			}
		}catch(InterruptedException exe){
			exe.printStackTrace();
		}
	}
}
public class SyncCollection {
	public static void main(String[] args){
		TreeSet<String> tsStr=new TreeSet<String>();		//tsStr本来不是同步集合
		Collection<String> syncCol=Collections.synchronizedCollection(tsStr);	//把tsSet设为同步集合
		syncCol.add("Gamma");
		syncCol.add("Beta");
		syncCol.add("Alpha");
		new MyThread(syncCol);		//启动第二个线程
		try{
			synchronized(syncCol){	//进入临界资源区域,在离开区域之前,本线程独占资源col
				for(String str:syncCol){
					System.out.println("Main Thread:"+str);	//读取集合
					Thread.sleep(500);
				}
			}
		}catch(InterruptedException exe){
			exe.printStackTrace();
		}
		
	}
}

有时希望保证集合不被修改,比如将集合传递给第三方代码。

Collection<Character> immutableCol=Colleactions.unmodifiableCollection(list);

Properties中的每个键和值都字符串。

Properties prop=new Properties();

prop.setProperty(“Tom”,”tom@hschhildt.com”);

prop.setProperty(“Ken”,”ken@hschhildt.com”);

prop.setProperty(“Steven”,”steven@hschhildt.com”);

//Properties转换成HashMap

HashMap<String,String> propMap=new HashMap<String,String>((Map) prop);

//hashMap转换成Set,从而对其元素进行遍历

Set<Map.Entry<String,String>> propSet=propMap.entrySet();

for(Map.Entry<String,String> me:propSet){}

posted @ 2011-09-19 15:26  张朝阳  阅读(1206)  评论(0编辑  收藏  举报