[java優先隊列PriorityQueue的使用]
PriorityQueue彈出優先級最高的元素,優先級的比較是通過元素實現Comparable接口或者傳入一個Comparator參數構造隊列實現元素的比較而計算出優先級的。像Integer、String和Character這樣的內置類型,默認使用12345 abcd一樣的自然排序。對于其他對象,默認會拋出異常。
常用方法:offer() 插入一個對象,這個對象會被排序,失敗返回falseadd() 插入一個對象,這個對象會被排序,失敗拋出異常poll() 返回優先級最高的元素,并刪除該元素 沒有元素返回nullremove()返回優先級最高的元素,并刪除該元素,沒有元素拋出異常peek() 返回優先級最高的元素,不刪除該元素,沒有元素返回nullelement() 返回優先級最高的元素,不刪除該元素,沒有元素拋出異常
文檔中推薦使用 offer()和poll()。要注意的是PriorityQueue維護的并不是一個有序表,并不保證所有元素有序,只確保彈出的是優先級最高的元素。
import
java.util.LinkedList;
import
java.util.PriorityQueue;
import
java.util.Queue;
import
java.util.Random;
class
Student
implements
Comparable {
String name;
int
age;
public
Student(String name,
int
age) {
super
();
this
.name = name;
this
.age = age;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
@Override
public
String toString() {
return
"Student [name="
- name +
", age=" - age +
"]"
;
}
@Override
public
int
compareTo(Object arg0) {
Student s = (Student) arg0;
return
this
.age < s.getAge() ? -
1
:
this
.age == s.getAge() ?
0
:
1
;
}
}
public
class
PriorityQueueDemo {
public
static
void
main(String[] args) {
Queue<Integer> pq0 =
new
LinkedList<Integer>();
Random random =
new
Random();
for
(
int
i =
0
; i <
10
; i++) {
pq0.add(
new
Integer(random.nextInt(
100
)));
}
pq0.offer(
123
);
System.out.println(
"queue:"
);
System.out.println(pq0);
System.out.println(pq0.poll());
System.out.println(pq0);
Queue<Integer> pq1 =
new
PriorityQueue<Integer>();
for
(
int
i =
0
; i <
10
; i++) {
pq1.add(
new
Integer(random.nextInt(
100
)));
}
System.out.println(
"PriorityQueue:"
);
System.out.println(pq1);
System.out.println(pq1.poll());
System.out.println(pq1);
Queue<Student> pq =
new
PriorityQueue<Student>();
Student s1 =
new
Student(
"zhang1"
,
24
);
Student s2 =
new
Student(
"zhang2"
,
23
);
Student s3 =
new
Student(
"zhang3"
,
25
);
Student s4 =
new
Student(
"zhang4"
,
22
);
pq.add(s1);
pq.add(s2);
pq.add(s3);
pq.add(s4);
System.out.println(pq);
System.out.println(pq.poll());
}
}
執行結果:queue:[57, 47, 65, 46, 55, 13, 6, 61, 36, 60, 123]57[47, 65, 46, 55, 13, 6, 61, 36, 60, 123]PriorityQueue:[9, 11, 18, 18, 41, 38, 22, 64, 34, 86]9[11, 18, 18, 34, 41, 38, 22, 64, 86][Student [name=zhang4, age=22], Student [name=zhang2, age=23], Student [name=zhang3, age=25], Student [name=zhang1, age=24]]Student [name=zhang4, age=22]
設計模式
作者 codercjg 在 18 一月 2015, 4:26 下午
行為模式:1.觀察者模式應用場景:當一個對象發生改變時,通知一個或多個依賴它的對象,java提供了類Observable和接口Observer分別代表被觀察者和觀察者。
import
java.util.Observable;
import
java.util.Observer;
//觀察者
class
Watched
extends
Observable {
private
String data =
""
;
public
void
setData(String data) {
if
(!
this
.data.equals(data)) {
this
.data = data;
this
.setChanged();
this
.notifyObservers();
}
}
public
String getData() {
return
data;
}
}
//被觀察者
class
Watcher
implements
Observer {
@Override
public
void
update(Observable arg0, Object arg1) {
System.out.println(
"changed "
- ((Watched) arg0).getData());
}
}
public
class
ObserverDemo {
public
static
void
main(String[] args) {
Observer watcher =
new
Watcher();
Watched watched =
new
Watched();
System.out.println(
"add observer"
);
watched.addObserver(watcher);
watched.setData(
"1"
);
watched.setData(
"2"
);
watched.setData(
"2"
);
watched.deleteObserver(watcher);
System.out.println(
"delete observer"
);
watched.setData(
"4"
);
}
}
2.模板方法模式使用場景:在模板中實現不會改變的算法框架,通過一個抽象方法把會變化的算法步驟延遲到子類中實現
abstract
class
Mp3Download {
// 延遲到子類中實現
protected
abstract
String search(String songTitle);
private
void
download(String url) {
System.out.println(
"download "
- url);
}
// 模板方法
public
void
getMp3(String songTitle) {
String title = search(songTitle);
download(title);
}
}
class
BaiduMp3
extends
Mp3Download {
@Override
protected
String search(String songTitle) {
System.out.println(
"baidu searching "
- songTitle);
String url =
"http://www.baidu.com/"
- songTitle;
return
url;
}
}
class
GoogleMp3
extends
Mp3Download {
@Override
protected
String search(String songTitle) {
System.out.println(
"Google searching "
- songTitle);
String url =
"http://www.Google.com/"
- songTitle;
return
url;
}
}
public
class
TemplateDemo {
public
static
void
main(String[] args) {
Mp3Download googleDownload =
new
GoogleMp3();
Mp3Download baiduDownload =
new
BaiduMp3();
googleDownload.getMp3(
"my heart will go on"
);
baiduDownload.getMp3(
"my heart will go on"
);
}
}
3.策略模式使用場景:算法實現與算法調用分離,使軟件有很多可替換的算法實現,比如java集合類中的Comparator
interface
Strategy{
int
compare(
int
a,
int
b);
}
class
Strategy1
implements
Strategy{
@Override
public
int
compare(
int
a,
int
b) {
return
a<b?
1
:
0
;
}
}
class
Strategy2
implements
Strategy{
@Override
public
int
compare(
int
a,
int
b) {
return
a>b?
1
:
0
;
}
}
class
Context{
private
Strategy strategy;
public
Context(Strategy strategy){
this
.strategy = strategy;
}
public
Strategy getStrategy() {
return
strategy;
}
public
void
setStrategy(Strategy strategy) {
this
.strategy = strategy;
}
public
int
compare(
int
a,
int
b) {
return
strategy.compare(a, b);
}
}
public
class
StrategyDemo {
public
static
void
main(String[] args) {
Strategy s1 =
new
Strategy1();
Strategy s2 =
new
Strategy2();
Context context =
new
Context(s1);
context.compare(
1
,
2
);
context.setStrategy(s2);
context.compare(
1
,
2
);
}
}
4.狀態模式使用場景:對象有很多種狀態,每一種狀態都需要表現不同的行為
interface
State {
void
handle();
void
next(StateManager stateMachine);
}
class
State1
implements
State {
@Override
public
void
handle() {
System.out.println(
"state1"
);
}
@Override
public
void
next(StateManager stateMachine) {
stateMachine.setState(
new
State2());
}
}
class
State2
implements
State {
@Override
public
void
handle() {
System.out.println(
"state2"
);
}
@Override
public
void
next(StateManager stateMachine) {
stateMachine.setState(
new
State3());
}
}
class
State3
implements
State {
@Override
public
void
handle() {
System.out.println(
"state3"
);
}
@Override
public
void
next(StateManager stateMachine) {
stateMachine.setState(
null
);
}
}
class
StateManager {
private
State state;
public
StateManager(State state) {
this
.state = state;
}
public
State getState() {
return
state;
}
public
void
setState(State state) {
this
.state = state;
}
public
void
manageState() {
if
(state !=
null
){
state.handle();
state.next(
this
);
}
}
}
public
class
StateDemo {
public
static
void
main(String[] args) {
State state1 =
new
State1();
StateManager stateManager =
new
StateManager(state1);
while
(stateManager.getState() !=
null
){
stateManager.manageState();
}
}
}
創建模式:1.單例模式使用場景:確保該類只存在一個對象
class
SingleObj {
private
static
volatile
SingleObj instance;
// 私有構造函數保證其他類中不能通過new創建對象
private
SingleObj() {
}
// 保證多線程環境中只創建一個對象
public
static
SingleObj getInstance() {
if
(instance ==
null
) {
synchronized
(SingleObj.
class
) {
if
(instance ==
null
) {
instance =
new
SingleObj();
}
}
}
return
instance;
}
}
ListView+ViewHolder模式+線程池
作者 codercjg 在 16 一月 2015, 10:11 下午
ListView重繪時會調用getView(int position, View convertView, ViewGroup parent)方法,其中的convertView有可能會被重用。ViewHold模式是用的很普遍的了。多個線程異步下載刷新ListView中進度條時因為convertView的重用需要注意避免顯示錯位。當listView的layout_height設置為wrap_content時,會多次重復調用getView(), 如果設置為match_parent就沒問題了。
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
"match_parent"
android:layout_height
"match_parent"
android:orientation
"horizontal"
<
TextView
android:id
"@+id/taskid"
android:layout_width
"wrap_content"
android:layout_height
"wrap_content"
android:text
"111"
/>
<
ProgressBar
android:id
"@+id/progressbar"
android:layout_width
"match_parent"
android:layout_height
"15dip"
style
"@android:style/Widget.ProgressBar.Horizontal"
android:max
"100"
/>
</
LinearLayout
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:tools
"http://schemas.android.com/tools"
android:id
"@+id/container"
android:layout_width
"match_parent"
android:layout_height
"match_parent"
tools:context
"com.codercjg.threadtest.MainActivity"
tools:ignore
"MergeRootFrame"
android:orientation
"vertical"
<
ListView
android:id
"@+id/listview"
android:layout_width
"match_parent"
android:layout_height
"match_parent"
</
ListView
</
LinearLayout
package
com.codercjg.threadtest;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
import
android.content.Context;
import
android.os.AsyncTask;
import
android.os.Bundle;
import
android.os.SystemClock;
import
android.support.v7.app.ActionBarActivity;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.BaseAdapter;
import
android.widget.ListView;
import
android.widget.ProgressBar;
import
android.widget.TextView;
public
class
MainActivity
extends
ActionBarActivity {
private
static
ExecutorService singleTaskExcutor = Executors.newSingleThreadExecutor();
// 列表項一個一個的刷新進度
private
static
ExecutorService limitedTaskExcutor = Executors.newFixedThreadPool(
10
);
// 10個列表項一起刷新進度
private
static
ExecutorService fullTaskExcutor = Executors.newCachedThreadPool();
// 所有列表項一起刷新進度
private
MyListAdapter listAdapter;
private
List<String> resPaths =
new
ArrayList<String>();
private
Map<String, ResInfo> map =
new
HashMap<String, ResInfo>();
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listview);
listAdapter =
new
MyListAdapter(
this
,
40
);
listView.setAdapter(listAdapter);
}
private
class
MyAsyncTask
extends
AsyncTask<Void, Integer, Void> {
private
String resPath;
public
MyAsyncTask(String resPath) {
this
.resPath = resPath;
}
@Override
protected
void
onProgressUpdate(Integer... values) {
super
.onProgressUpdate(values);
ResInfo resInfo = map.get(resPath);
resInfo.progress = values[
0
];
if
(resInfo.holder !=
null
){
// 如果列表項已被用于顯示其他資源進度
resInfo.holder.progBar.setProgress(values[
0
]);
}
}
@Override
protected
Void doInBackground(Void... arg0) {
int
prog =
0
;
while
(prog <
100
) {
SystemClock.sleep(
100
);
prog++;
publishProgress(prog);
}
return
null
;
}
}
private
class
MyListAdapter
extends
BaseAdapter {
private
Context context;
private
LayoutInflater inflater;
private
int
count;
public
MyListAdapter(Context context,
int
count) {
this
.context = context;
this
.count = count;
inflater = LayoutInflater.from(context);
String path;
ResInfo resInfo;
for
(
int
i =
0
; i < count; i++) {
path = String.valueOf(i);
resPaths.add(path);
resInfo =
new
ResInfo();
map.put(path, resInfo);
}
}
@Override
public
int
getCount() {
return
resPaths.size();
}
@Override
public
Object getItem(
int
arg0) {
return
resPaths.get(arg0);
}
@Override
public
long
getItemId(
int
position) {
return
position;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
ViewHolder holder;
if
(convertView ==
null
) {
convertView = inflater.inflate(R.layout.my_list_item, parent,
false
);
holder =
new
ViewHolder();
holder.progBar = (ProgressBar) convertView.findViewById(R.id.progressbar);
holder.textView = (TextView) convertView.findViewById(R.id.taskid);
holder.resPath = resPaths.get(position);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
System.out.println(
"recycle item id:"
- holder.resPath);
}
String resPath = resPaths.get(position);
ResInfo resInfo = map.get(resPath);
if
(resInfo.task ==
null
) {
// 如果當前列表項關聯的資源沒有線程下載
MyAsyncTask task =
new
MyAsyncTask(resPath);
//創建一個線程
resInfo.task = task;
// task.execute(); // 一次執行一個線程
// task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);//一列表項刷新
// task.executeOnExecutor(singleTaskExcutor); // 一列表項刷新
// task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);//多個線程一起執行和具體系統
//task.executeOnExecutor(limitedTaskExcutor); // 10個列表項一起刷新,
task.executeOnExecutor(fullTaskExcutor);
// 所有列表項一起刷新
}
if
(holder.resPath != resPath) {
// 如果當前列表項已經顯示了資源,但不是當前資源
map.get(holder.resPath).holder =
null
;
holder.resPath = resPath;
}
map.get(resPaths.get(position)).holder = holder;
holder.textView.setText(resPath);
holder.progBar.setProgress(resInfo.progress);
return
convertView;
}
}
private
static
class
ViewHolder {
public
ProgressBar progBar;
public
TextView textView;
public
String resPath;
}
private
class
ResInfo {
int
progress;
ViewHolder holder;
MyAsyncTask task;
}
}