??xml version="1.0" encoding="utf-8" standalone="yes"?>
方式有四U:?/span> ThreadLocal ?/span> synchronized( ) ?/span> wait() ?/span> notify() ?/span> volatile
目的Q都是ؓ了解军_U程中的对同一变量的访问冲H?br />
ThreadLocal
. ?/span> ThreadLocal 保证不同U程拥有不同实例Q相同线E一定拥有相同的实例Q即为每一个用该变量的线E提供一个该变量值的副本Q每一个线E都可以独立改变自己的副本,而不是与其它U程的副本冲H?/span>
. ㈡优势:提供了线E安全的׃n对象
. ㈢与其它同步机制的区别:同步机制是ؓ了同步多个线E对相同资源的ƈ发访问,是ؓ了多个线E之间进行通信Q?/span> ThreadLocal 是隔d个线E的数据׃nQ从Ҏ上就不在多个U程之间׃n资源Q这样当然不需要多个线E进行同步了?/span>
. ㈣用技巧:需要多个线E之间进行通信Q用同步机Ӟ如果需要隔d个线E之间的׃n冲突Q推荐?/span> ThreadLocal Q线E安全)
volatile
.?/span>volatile 修饰的成员变量在每次被线E访问时Q都从共享内存中重读该成员变量的倹{而且Q当成员变量发生变化ӞU程变化值回写到׃n内存?br />
.㈡优势:q样在Q何时刻,两个不同的线EL看到某个成员变量的同一个倹{?/span>
. ㈢缘由:Java 语言规范中指出:Z获得最佳速度Q允许线E保存共享成员变量的U有拯Q而且只当U程q入或者离开同步代码块时才与׃n成员变量的原始值对比?br />
q样当多个线E同时与某个对象交互Ӟ必要注意到要让线E及时的得到׃n成员变量的变化?/span>
?/span> volatile 关键字就是提C?/span> VM Q对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互?/span>
. ㈣用技巧:在两个或者更多的U程讉K的成员变量上使用 volatile 。当要访问的变量已在 synchronized 代码块中Q或者ؓ帔RӞ不必使用?/span>
׃使用 volatile 屏蔽掉了 VM 中必要的代码优化Q所以在效率上比较低Q因此一定在必要时才使用此关键字?br />
阐释Q?br />
U程Z提高效率Q将某成员变?/span>(?/span>A)拯了一份(?/span>BQ,U程中对A的访问其实访问的?/span>B?/span>
只在某些动作时才q行A?/span>B的同步,因此存在A?/span>B不一致的情况?/span>volatile是用来避免q种情况的?/span>
volatile告诉jvmQ?/span>它所修饰的变量不保留拯Q直接访问主内存中的Q也是上面说的A)
sleep() vs wait()
sleep是线E类QThreadQ的ҎQ导致此U程暂停执行指定旉Q把执行Zl其他线E,但是监控状态依然保持,到时后会自动恢复?br />
调用sleep不会释放对象锁?br />
wait是ObjectcȝҎQ对此对象调用waitҎD本线E放弃对象锁Q进入等待此对象的等待锁定池Q只有针Ҏ对象发出notifyҎQ或notifyAllQ后本线E才
q入对象锁定池准备获得对象锁q入q行状态?br />
===================2007-05-01引用如下内容===========
protected Object initialValue() { return null; } |
public class ThreadLocal { private Map values = Collections.synchronizedMap(new HashMap()); public Object get() { Thread curThread = Thread.currentThread(); Object o = values.get(curThread); if (o == null && !values.containsKey(curThread)) { o = initialValue(); values.put(curThread, o); } return o; } public void set(Object newValue) { values.put(Thread.currentThread(), newValue); } public Object initialValue() { return null; } } |
public class SerialNum { // The next serial number to be assigned private static int nextSerialNum = 0; private static ThreadLocal serialNum = new ThreadLocal() { protected synchronized Object initialValue() { return new Integer(nextSerialNum++); } }; public static int get() { return ((Integer) (serialNum.get())).intValue(); } } |
int serial = SerialNum.get(); |
多线E之间需要协调工作。例如,览器的一个显C图片的U程displayThread惌执行昄囄的Q务,必须{待下蝲U程downloadThread该囄下蝲完毕。如果图片还没有下蝲完,displayThread可以暂停Q当downloadThread完成了Q务后Q再通知displayThread“囄准备完毕Q可以显CZ”Q这ӞdisplayThreadl箋执行?
以上逻辑单的说就是:如果条g不满I则等待。当条g满Ӟ{待该条件的U程被唤醒。在Java中,q个机制的实C赖于wait/notify。等待机制与锁机制是密切兌的。例如:
synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}
当线EA获得了obj锁后Q发现条件condition不满I无法l箋下一处理Q于是线EAwait() , 攑ּ对象?
之后在另一U程B中,如果B更改了某些条Ӟ使得U程A的condition条g满了,可以唤醒线EAQ?/p>
synchronized(obj) {
condition = true;
obj.notify();
}
需要注意的概念是:
# 调用obj的wait(), notify()Ҏ前,必须获得obj锁,也就是必d在synchronized(obj) {...} 代码D内?/p>
# 调用obj.wait()后,U程A释放了obj的锁Q否则线EB无法获得obj锁,也就无法在synchronized(obj) {...} 代码D内唤醒A?/p>
# 当obj.wait()Ҏq回后,U程A需要再ơ获得obj锁,才能l箋执行?/p>
# 如果A1,A2,A3都在obj.wait()Q则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM军_Q?/p>
# obj.notifyAll()则能全部唤醒A1,A2,A3Q但是要l箋执行obj.wait()的下一条语句,必须获得obj锁,因此QA1,A2,A3只有一个有Z获得锁l执行,例如A1Q其余的需要等待A1释放obj锁之后才能l执行?/p>
# 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此QA1,A2,A3虽被唤醒Q但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后QA1,A2,A3中的一个才有机会获得锁l箋执行?/p>
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class InsertSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int temp;
for(int i=1;i<data.length;i++){
for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
SortUtil.swap(data,j,j-1);
}
}
}
}
冒排序Q?/p>
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class BubbleSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int temp;
for(int i=0;i<data.length;i++){
for(int j=data.length-1;j>i;j--){
if(data[j]<data[j-1]){
SortUtil.swap(data,j,j-1);
}
}
}
}
}
选择排序Q?/p>
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class SelectionSort implements SortUtil.Sort {
/*
* (non-Javadoc)
*
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int temp;
for (int i = 0; i < data.length; i++) {
int lowIndex = i;
for (int j = data.length - 1; j > i; j--) {
if (data[j] < data[lowIndex]) {
lowIndex = j;
}
}
SortUtil.swap(data,i,lowIndex);
}
}
}
Shell排序Q?/p>
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class ShellSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
for(int i=data.length/2;i>2;i/=2){
for(int j=0;j<i;j++){
insertSort(data,j,i);
}
}
insertSort(data,0,1);
}
/**
* @param data
* @param j
* @param i
*/
private void insertSort(int[] data, int start, int inc) {
int temp;
for(int i=start+inc;i<data.length;i+=inc){
for(int j=i;(j>=inc)&&(data[j]<data[j-inc]);j-=inc){
SortUtil.swap(data,j,j-inc);
}
}
}
}
快速排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class QuickSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
quickSort(data,0,data.length-1);
}
private void quickSort(int[] data,int i,int j){
int pivotIndex=(i+j)/2;
file://swap
SortUtil.swap(data,pivotIndex,j);
int k=partition(data,i-1,j,data[j]);
SortUtil.swap(data,k,j);
if((k-i)>1) quickSort(data,i,k-1);
if((j-k)>1) quickSort(data,k+1,j);
}
/**
* @param data
* @param i
* @param j
* @return
*/
private int partition(int[] data, int l, int r,int pivot) {
do{
while(data[++l]<pivot);
while((r!=0)&&data[--r]>pivot);
SortUtil.swap(data,l,r);
}
while(l<r);
SortUtil.swap(data,l,r);
return l;
}
}
改进后的快速排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class ImprovedQuickSort implements SortUtil.Sort {
private static int MAX_STACK_SIZE=4096;
private static int THRESHOLD=10;
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int[] stack=new int[MAX_STACK_SIZE];
int top=-1;
int pivot;
int pivotIndex,l,r;
stack[++top]=0;
stack[++top]=data.length-1;
while(top>0){
int j=stack[top--];
int i=stack[top--];
pivotIndex=(i+j)/2;
pivot=data[pivotIndex];
SortUtil.swap(data,pivotIndex,j);
file://partition
l=i-1;
r=j;
do{
while(data[++l]<pivot);
while((r!=0)&&(data[--r]>pivot));
SortUtil.swap(data,l,r);
}
while(l<r);
SortUtil.swap(data,l,r);
SortUtil.swap(data,l,j);
if((l-i)>THRESHOLD){
stack[++top]=i;
stack[++top]=l-1;
}
if((j-l)>THRESHOLD){
stack[++top]=l+1;
stack[++top]=j;
}
}
file://new InsertSort().sort(data);
insertSort(data);
}
/**
* @param data
*/
private void insertSort(int[] data) {
int temp;
for(int i=1;i<data.length;i++){
for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
SortUtil.swap(data,j,j-1);
}
}
}
}
归ƈ排序Q?/p>
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class MergeSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int[] temp=new int[data.length];
mergeSort(data,temp,0,data.length-1);
}
private void mergeSort(int[] data,int[] temp,int l,int r){
int mid=(l+r)/2;
if(l==r) return ;
mergeSort(data,temp,l,mid);
mergeSort(data,temp,mid+1,r);
for(int i=l;i<=r;i++){
temp[i]=data[i];
}
int i1=l;
int i2=mid+1;
for(int cur=l;cur<=r;cur++){
if(i1==mid+1)
data[cur]=temp[i2++];
else if(i2>r)
data[cur]=temp[i1++];
else if(temp[i1]<temp[i2])
data[cur]=temp[i1++];
else
data[cur]=temp[i2++];
}
}
}
改进后的归ƈ排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class ImprovedMergeSort implements SortUtil.Sort {
private static final int THRESHOLD = 10;
/*
* (non-Javadoc)
*
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
int[] temp=new int[data.length];
mergeSort(data,temp,0,data.length-1);
}
private void mergeSort(int[] data, int[] temp, int l, int r) {
int i, j, k;
int mid = (l + r) / 2;
if (l == r)
return;
if ((mid - l) >= THRESHOLD)
mergeSort(data, temp, l, mid);
else
insertSort(data, l, mid - l + 1);
if ((r - mid) > THRESHOLD)
mergeSort(data, temp, mid + 1, r);
else
insertSort(data, mid + 1, r - mid);
for (i = l; i <= mid; i++) {
temp[i] = data[i];
}
for (j = 1; j <= r - mid; j++) {
temp[r - j + 1] = data[j + mid];
}
int a = temp[l];
int b = temp[r];
for (i = l, j = r, k = l; k <= r; k++) {
if (a < b) {
data[k] = temp[i++];
a = temp[i];
} else {
data[k] = temp[j--];
b = temp[j];
}
}
}
/**
* @param data
* @param l
* @param i
*/
private void insertSort(int[] data, int start, int len) {
for(int i=start+1;i<start+len;i++){
for(int j=i;(j>start) && data[j]<data[j-1];j--){
SortUtil.swap(data,j,j-1);
}
}
}
}
堆排序:
package org.rut.util.algorithm.support;
import org.rut.util.algorithm.SortUtil;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class HeapSort implements SortUtil.Sort{
/* (non-Javadoc)
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
*/
public void sort(int[] data) {
MaxHeap h=new MaxHeap();
h.init(data);
for(int i=0;i<data.length;i++)
h.remove();
System.arraycopy(h.queue,1,data,0,data.length);
}
private static class MaxHeap{
void init(int[] data){
this.queue=new int[data.length+1];
for(int i=0;i<data.length;i++){
queue[++size]=data[i];
fixUp(size);
}
}
private int size=0;
private int[] queue;
public int get() {
return queue[1];
}
public void remove() {
SortUtil.swap(queue,1,size--);
fixDown(1);
}
file://fixdown
private void fixDown(int k) {
int j;
while ((j = k << 1) <= size) {
if (j < size && queue[j]<queue[j+1])
j++;
if (queue[k]>queue[j]) file://?/font>用交?br> break;
SortUtil.swap(queue,j,k);
k = j;
}
}
private void fixUp(int k) {
while (k > 1) {
int j = k >> 1;
if (queue[j]>queue[k])
break;
SortUtil.swap(queue,j,k);
k = j;
}
}
}
}
SortUtilQ?/p>
package org.rut.util.algorithm;
import org.rut.util.algorithm.support.BubbleSort;
import org.rut.util.algorithm.support.HeapSort;
import org.rut.util.algorithm.support.ImprovedMergeSort;
import org.rut.util.algorithm.support.ImprovedQuickSort;
import org.rut.util.algorithm.support.InsertSort;
import org.rut.util.algorithm.support.MergeSort;
import org.rut.util.algorithm.support.QuickSort;
import org.rut.util.algorithm.support.SelectionSort;
import org.rut.util.algorithm.support.ShellSort;
/**
* @author treeroot
* @since 2006-2-2
* @version 1.0
*/
public class SortUtil {
public final static int INSERT = 1;
public final static int BUBBLE = 2;
public final static int SELECTION = 3;
public final static int SHELL = 4;
public final static int QUICK = 5;
public final static int IMPROVED_QUICK = 6;
public final static int MERGE = 7;
public final static int IMPROVED_MERGE = 8;
public final static int HEAP = 9;
public static void sort(int[] data) {
sort(data, IMPROVED_QUICK);
}
private static String[] name={
"insert", "bubble", "selection", "shell", "quick", "improved_quick", "merge", "improved_merge", "heap"
};
private static Sort[] impl=new Sort[]{
new InsertSort(),
new BubbleSort(),
new SelectionSort(),
new ShellSort(),
new QuickSort(),
new ImprovedQuickSort(),
new MergeSort(),
new ImprovedMergeSort(),
new HeapSort()
};
public static String toString(int algorithm){
return name[algorithm-1];
}
public static void sort(int[] data, int algorithm) {
impl[algorithm-1].sort(data);
}
public static interface Sort {
public void sort(int[] data);
}
public static void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
解决一Q?/p>
陷阱Q?br>Calendar中的MONTH字段和数l下标一P?开始,0代表Calendar.JANUARYQ?代表Calendar.FEBUARY……12代表ơ年Calendar.JANUARY。因此用戯入的月䆾在置入Calendar对象之前必须q行处理Q即减一?br>
解决二:
1. 数组的基本特?/span>
数组与其它种cȝ容器(List/Set/Map)之间的区别在于效率、确定的cd和保存基本类型数据的能力。数l是一U高效的存储和随问对象引用序列的方式Q用数l可以快速的讉K数组中的元素。但是当创徏一个数l对?/span>(注意和对象数l的区别)后,数组的大也固定了Q当数组I间不的时候就再创Z个新的数l,把旧的数l中所有的引用复制到新的数l中?/span>
Java中的数组和容器都需要进行边界检查,如果界׃得到一?/span>RuntimeException异常。这点和C++中有所不同Q?/span>C++?/span>vector的操作符[]不会做边界检查,q在速度上会有一定的提高Q?/span>Java的数l和容器会因为时d在的边界查带来一些性能上的开销?/span>
Java中通用的容器类不会以具体的cd来处理对象,容器中的对象都是?/span>Objectcd处理的,q是Java中所有类的基cR另外,数组可以保存基本cdQ而容器不能,它只能保存Q意的Java对象?/span>
一般情况下Q考虑到效率与cd查,应该可能考虑使用数组。如果要解决一般化的问题,数组可能会受C些限Ӟq时可以使用Java提供的容器类?/span>
2. 操作数组的实用功?/span>
?/span>java.util.ArrayscMQ有许多static静态方法,提供了操作数l的一些基本功能:
equals()Ҏ----用于比较两个数组是否相等Q相{的条g是两个数l的元素个数必须相等Qƈ且对应位|的元素也相{?/span>
fill()Ҏ----用以某个值填充整个数l,q个Ҏ有点W?/span>
asList()Ҏ----接受L的数lؓ参数Q将其{变ؓList容器?/span>
binarySearch()Ҏ----用于在已l排序的数组中查扑օ素,需要注意的是必L已经排序q的数组。当Arrays.binarySearch()扑ֈ了查扄标时Q该Ҏ返回一个等于或大于0的|否则返回一个负|表示在该数组目前的排序状态下此目标元素所应该插入的位|。负值的计算公式?/span>“-x
sort()Ҏ----Ҏl进行升序排序?/span>
?/span>Java标准cd中,另有staticҎSystem.arraycopy()用来复制数组Q它针对所有类型做了重载?/span>
3. 数组的排?/span>
?/span>Java1.0?/span>1.1两个版本中,cd~少基本的算法操作,包括排序的操作,Java2Ҏq行了改善。在q行排序的操作时Q需要根据对象的实际cd执行比较操作Q如果ؓ每种不同的类型各自编写一个不同的排序ҎQ将会得代码很难被复用。一般的E序设计目标应是“保持不变的事物与会发改变的事物相分?#8221;。在q里Q不变的是通用的排序算法,变化的是各种对象怺比较的方式?/span>
Java有两U方式来实现比较的功能,一U是实现java.lang.Comparable接口Q该接口只有一?/span>compareTo()ҎQƈ以一?/span>ObjectcMؓ参数Q如果当前对象小于参数则q回负|如果相等q回Ӟ如果当前对象大于参数则返回正倹{另一U比较方法是采用{略(strategy)设计模式Q将会发生变化的代码装在它自己的类({略对象)中,再将{略对象交给保持不变的代码中Q后者用此{略实现它的法。因此,可以Z同的比较方式生成不同的对象,它们用在同L排序E序中。在此情况下Q通过定义一个实CComparator接口的类而创Z一个策略,q个{略cLcompare()?/span>equals()两个ҎQ一般情况下实现compare()Ҏ卛_?/span>
使用上述两种Ҏ卛_对Q意基本类型的数组q行排序Q也可以对Q意的对象数组q行排序。再提示一遍,基本cd数组无法使用Comparatorq行排序?/span>
Java标准cd中的排序法针对排序的类型进行了优化——针对基本类型设计了“快速排?#8221;Q针对对象设计的“E_归ƈ排序”。一般不用担心其性能?br>
可以用两个方法来分割字符串ؓ数组.
1. java.lang.String ?split() Ҏ, JDK 1.4 or later
public String[] split(String regex, int limit)
此方法返回的数组包含此字W串的每个子字符Ԍq些子字W串由另一个匹配给定的表达式的子字W串l止或由字符串结束来l止。数l中的子字符串按它们在此字符串中的顺序排列。如果表辑ּ不匹配输入的M部分Q则l果数组只具有一个元素,x字符丌Ӏ?
limit 参数控制模式应用的次敎ͼ因此影响l果数组的长度。如果该限制 n 大于 0Q则模式被最多应?n - 1 ơ,数组的长度将不会大于 nQ而且数组的最后项包含超出最后匹配的定界W的所有输入。如?n 为非正,则模式将被应用尽可能多的ơ数Q而且数组可以是Q意长度。如?n 为零Q则模式被应用可能多的次敎ͼ数组可有M长度Qƈ且结字符串将被丢弃?
例如Q字W串 "boo:and:foo" 使用q些参数可生成下列结果:
Regex
Limit
l果:
2
{ "boo", "and:foo" }:
5
{ "boo", "and", "foo" }:
-2
{ "boo", "and", "foo" }o
5
{ "b", "", ":and:f", "", "" }o
-2
{ "b", "", ":and:f", "", "" }o
0
{ "b", "", ":and:f" }
q种形式的方法调?str.split(regex, n) 产生与以下表辑ּ完全相同的结果:
Pattern
.compile
(regex).split
(str, n)
regex
- 定界正则表达?
limit
- l果阈|如上所q?
PatternSyntaxException
- 如果正则表达式的语法无效
Pattern
public String[] split(String regex)
该方法的作用像是用给定的表达式和限制参数 0 来调用两参数 split
Ҏ。因此,l果数组中不包括l尾I字W串?
例如Q字W串 "boo:and:foo" 产生带有下面q些表达式的l果Q?
Regex
l果:
{ "boo", "and", "foo" }o
{ "b", "", ":and:f" }
regex
- 定界正则表达?
PatternSyntaxException
- 如果正则表达式的语法无效
Pattern
2. java.util.Tokenizer JDK 1.0 or later
string tokenizer cd许应用程序将字符串分解ؓ标记。tokenization Ҏ?StreamTokenizer
cL使用的方法更单?code>StringTokenizer Ҏ不区分标识符、数和带引号的字W串Q它们也不识别ƈ跌注释?
可以在创建时指定Q也可以Ҏ每个标记来指定分隔符Q分隔标记的字符Q集合?
StringTokenizer
的实例有两种行ؓ方式Q这取决于它在创建时使用?returnDelims
标志的值是 true
q是 false
Q?
false
Q则分隔W字W用来分隔标记。标记是q箋字符Q不是分隔符Q的最大序列?
true
Q则认ؓ那些分隔W字W本w即为标记。因此标记要么是一个分隔符字符Q要么是那些q箋字符Q不是分隔符Q的最大序列?StringTokenizer 对象在内部维护字W串中要被标记的当前位置。某些操作将此当前位|移臛_处理的字W后?
通过截取字符串的一个子串来q回标记Q该字符串用于创?StringTokenizer 对象?
下面是一个?tokenizer 的实例。代码如下:
StringTokenizer st = new StringTokenizer("this is a test"); while (st.hasMoreTokens()) { System.out.println(st.nextToken()); }
输出以下字符Ԍ
this is a test
StringTokenizer 是出于兼Ҏ的原因而被保留的遗留类Q虽然在C码中q不鼓励使用它)。徏议所有寻求此功能的h使用 String ?split Ҏ?java.util.regex 包?
下面的示例阐明了如何使用 String.split Ҏ字W串分解为基本标讎ͼ
String[] result = "this is a test".split("\\s"); for (int x=0; x<result.length; x++) System.out.println(result[x]);
输出以下字符Ԍ
this is a test