TreeViewer和TableViewer在使用上还是有很多相似之处.TreeViewer中冶有TableViewer中的过滤器和排序器.具体使用看TableViewer中的使用.

和Table有JFace的扩展TableViewer一样,Tree也有一个JFace中的扩展,那就是TreeViewer.因为TreeViewer和TableViewer继承自同一个父类StructuredViewer所以两者有很多方法的使用是一样的.例如:都使用setInput方法输入数据,都有内容器,标签器,以及排序器,过滤器等.

建立一个树节点的接口类:

树节点由两个基本特征,名称和子节点.这里把这两个特征抽象出来写成一个接口,然后将要做树节点的实体类实现此接口.

主义这个接口不是必须的.仅仅是为了今后操作方便,以及规范化涉及才建立的.

但是每个实体对应的都是树上的一个节点.这里定义一个树中节点的通用接口.

然后每个实体类都实现这个接口.

接着建立几个实体类:

ITreeEntry.java

 /**
* 树上的每个一个节点都对应的是一个实体,这个实体是树上的一个节点.
* 首先在定义实体类(People City Country)之前要先定义这个接口ITreeEntry
* 树的节点接口
* @author kongxiaohan
*/
public interface ITreeEntry {
/*
* 设置dedao 树节点的名称
* 只声明抽象方法,不声明字段名
*/
public String getName();
public void setName(String name); /*
* 设置与得到子节点集合.
*/
public void setChildren(List<ITreeEntry> children);
public List<ITreeEntry> getChildren();
}

City.java

 /**
* City城市实体类
* @author kongxiaohan
*
*/
public class City implements ITreeEntry{
private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
private String name;// 城市名 private List<ITreeEntry> peoples;//City实体的子节点 城市中的人,装在一个List集合中 public City(String name) {
super();
this.name = name;
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} //这个地方是设置子节点....当前是City实体,其子节点是People实体
@Override
public void setChildren(List<ITreeEntry> children) {
//这个地方我犯了一错误,以前写习惯了,this.name = name
//所以一开始这个地方我写的是this.peoples = peoples
//在Country实体类中也是这个错误,所以运行出来的程序只有一列国家名,国家下面的城市都没有了....
this.peoples = children;
} @Override
public List<ITreeEntry> getChildren() {
return peoples;
}
}

Country.java

 /**
* Country国家实体类
* @author kongxiaohan
*/
public class Country implements ITreeEntry {
private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
private String name; // 国家名 private List<ITreeEntry> cities; //Country实体的子节点是城市 City 此国家所包含的的城市的集合,集合元素为City对象 public Country() {
} public Country(String name) {
super();
this.name = name;
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public void setChildren(List<ITreeEntry> children) {
this.cities = children;
} @Override
public List<ITreeEntry> getChildren() {
return cities;
}
}

People.java

 public class People implements ITreeEntry {
private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
private String name; // 姓名
private boolean sex; // 性别 true男,flase女
private int age; // 年龄
private Date createDate; // 记录的建立日期,是java.util.Date,而不是java.sql.Date public People(String name) {
super();
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
} //因为人是这个树的最小子节点,所以这个地方空实现接口中的这两个方法就可以了
@Override
public void setChildren(List<ITreeEntry> children) {
}
@Override
public List<ITreeEntry> getChildren() {
return null;
}
}

制造各个实体类的工具类

DataFactory.java

 /**
* 此类负责生成TreeViewer的方法setInput所需要的参数.
* @author kongxiaohan
*
* 这个地方我没有用书中用的局部代码块,在组织代码的时候确实犯了一些小错误,
* 确实体会到了局部代码块的意义,代码读起来容易,而且节省了内存.
*/
public class DataFactory {
/**
* 在这个方法中定义生成的数据
* 要有人People的数据对象
* 要有国家Country的数据对象
* 要有城市City的数据对象
* @return
*/
public static Object createTreeData(){
//生成人People的数据对象
People people1 = new People("张A");
People people2 = new People("张B");
People people3 = new People("张C");
People people4 = new People("张D");
People people5 = new People("张E");
People people6 = new People("张F");
People people7 = new People("张G");
People people8 = new People("张H");
People people9 = new People("张I"); //生成城市City的数据对象
City city1 = new City("北京");
City city2 = new City("广州");
City city3 = new City("东京");
City city4 = new City("芝加哥");
City city5 = new City("洛杉矶"); //生成国家Country的的数据对象
Country country1 = new Country("中国");
Country country2 = new Country("日本");
Country country3 = new Country("美国"); /**
* 将这些封装的对象建立关系.
*/
//1.人和城市的关系
//张A 张B 张C 在帝都
ArrayList<ITreeEntry> list1 = new ArrayList<ITreeEntry>();
list1.add(people1);
list1.add(people2);
list1.add(people3);
city1.setChildren(list1); //张D 张E 张F在广州
ArrayList<ITreeEntry> list2 = new ArrayList<ITreeEntry>();
list2.add(people4);
list2.add(people5);
list2.add(people6);
city2.setChildren(list2); //张G 在东京
ArrayList<ITreeEntry> list3 = new ArrayList<ITreeEntry>();
list3.add(people7);
city3.setChildren(list3); //张I 在芝加哥
ArrayList<ITreeEntry> list4 = new ArrayList<ITreeEntry>();
list4.add(people8);
city4.setChildren(list4); //张H 在洛杉矶
ArrayList<ITreeEntry> list5 = new ArrayList<ITreeEntry>();
list5.add(people9);
city5.setChildren(list5); //2.城市和国家的关系
//北京 上海 广州是中国的
ArrayList<ITreeEntry> list6 = new ArrayList<ITreeEntry>();
list6.add(city1);
list6.add(city2);
country1.setChildren(list6); //东京是日本的
ArrayList<ITreeEntry> list7 = new ArrayList<ITreeEntry>();
list7.add(city3);
country2.setChildren(list7); //芝加哥和洛杉矶是美国的
ArrayList<ITreeEntry> list8 = new ArrayList<ITreeEntry>();
list8.add(city4);
list8.add(city5);
country3.setChildren(list8); //3.将国家置于一个对象之下,这个对象可以是一个List也可以是个数组
//国家是这个树上的最上层的节点.国家和国家之间是并列的关系,把这几个国家放到一个List集合对象中.
ArrayList<ITreeEntry> list9 = new ArrayList<ITreeEntry>();
list9.add(country1);
list9.add(country2);
list9.add(country3);
return list9;
}
}

内容器:TreeViewerContentProvider.java

标签器还比较简单,在TreeViewer中最主要和最复杂的是内容器,熟悉内容器是掌握TreeViewer的要点.

 /**
* "内容器" 由它决定哪些对象记录应该输出在TreeViewer里显示.
* @author kongxiaohan
*
*/
public class TreeViewerContentProvider implements ITreeContentProvider{ /**
* 这个方法决定树的一级目录显示哪些对象
* @param inputElement 是用tv.setInput()方法输入的那个对象
* @return Object[]一个数组,数组中一个元素就是一个结点
*/
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof List) {
List list = (List) inputElement;
return list.toArray();
} else {
return new Object[0]; // 生成一个空数组
}
} /**
* 判断某结点是否有子结点。如果有子结点,这时结点前都有一个“+”号图标
*
* @param element 需要判断是否有子的结点
* @return true有子结点,false无子结点
*/
@Override
public boolean hasChildren(Object element) {
ITreeEntry entry = (ITreeEntry) element;
List<ITreeEntry> list = entry.getChildren();
if (list == null || list.isEmpty()) {
return false;
} else {
return true;
}
} /**
* 由这个方法决定父结点应该显示那些子结点。
*
* @param parentElement 当前被点击的结点对象
* @return 由子结点做为元素的数组
*/
@Override
public Object[] getChildren(Object parentElement) {
ITreeEntry entry = (ITreeEntry) parentElement;
List<ITreeEntry> list = entry.getChildren();
if (list == null || list.isEmpty()) {
return new Object[0];
} else {
return list.toArray();
}
} //>>>>>>>>>>>>>>>>>>>>>>>>>书上说以下三个方法是没有用的,空实现就哦了>>>>>>>>>>>>>>>>>>>>>>
@Override
public Object getParent(Object element) {
return null;
} @Override
public void dispose() {
} @Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}

程序说明:在内容器中最关键的是getElements,hasChildren,getChildren这三个方法.

1.getElements自在显示"第一级"结点的时候才会被执行.

2.hasChildren主要用于判断当前说系那是的节点是否有子节点,如果有子节点则前面显示一个"+"号图标,而有"+"号的结点则可以单击展开其下一级的子节点.

3.当单击右"子"的结点的时候,才会执行getChildren方法.展开其子节点后,又会对子节点执行一遍hasChildren方法,以决定其各子结点前是否显示"+"图标.

下面是"内容器"在启动,单击,关闭窗口时执行的过程.

下面以本例来解释这个图:

1.树界面启动的时候 ,先执行inputChanged()方法,接着执行getElements方法,其inputElement参数就是由setInput传入的对象:包含所有实体对象的List,此List在getElements中被转化成一个数组,数组包含第一级结点的两个元素,中国,美国,日本,他们将首先显示在页面上.接下来执行三次hasChildren方法,判断中国,日本和美国是否有子节点.他们都有子节点.,所以方法返回True,两结点前都显示"+"图标.

2.单击右子节点的中国:先执行一次getChildren方法,方法的parentElement参数就是中国结点对象.方法中把中国的子节点取出转换陈给一个数组返回,此数组包含3个元素"北京,上海,济南".接下来连续执行3次hasChildren方法来判断"北京,上海,济南"是否有子节点,如果有在结点的前面显示一个"+"图标.

3.单击没有子节点的结点:不会有执行内容器中的任何方法.

4.关闭窗口:会先后执行inputChanged和dispose方法.

标签器TreeViewerLableProvider.java

将标签器写成单独的外部类,以便于后面的实例共用,其代码如下,在getText方法中element的类型可以是国家,城市,人,由于他们都是属于一个接口,所以getText的代码简洁不少.getImage()的实现参考TableViewer的标签器.

 /**
* "标签器" 控制记录在树中显示的文字和图像等.
* @author kongxiaohan
*/
public class TreeViewerLableProvider implements ILabelProvider { /**
* 记录显示的文字。不能返回NULL值
*/
@Override
public String getText(Object element) {
//得到这个节点对应的名字,首先对element进行强制类型转换
ITreeEntry entry = (ITreeEntry) element;
return entry.getName();
} /**
* 记录显示的图像,可以返回NULL值
*/
@Override
public Image getImage(Object element) {
return null;
} //>>>>>>>>>>>>>>>>>>>>>>书上说一下几个方法没有用,空实现就可以了.>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
public void addListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub } @Override
public void removeListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub }
@Override
public void dispose() {
// TODO Auto-generated method stub }
@Override
public boolean isLabelProperty(Object element, String property) {
// TODO Auto-generated method stub
return false;
}
}

给TreeViewer加上右键菜单的方法和TableViewer相似,也要用到Action,ActionGroup,MenuManager类.当然程序要根据树的特点稍作改动.

MyActionGroup内含有各Action类,在实现Action时,对传入的结点对象要记得进行空值判断.因为TreeViewer的大部分方法都不支持空值参数.会导致异常并中断程序.

MyActionGroup.java

 public class MyActionGroup extends ActionGroup {
//ActionGroup这是个抽象类,但是其中并没有抽象方法.
private TreeViewer treeViewer; //构造方法
public MyActionGroup(TreeViewer treeViewer) {
this.treeViewer = treeViewer;
} /**
* 生成菜单Menu,并将两个Action传入
*/
public void fillContextMenu(IMenuManager mgr) {
/*
* 加入两个Action对象到菜单管理器
*/
MenuManager menuManager = (MenuManager) mgr; // 把接口类转换成其实现类.
//用MenuManager管理Action
menuManager.add(new OpenAction());
menuManager.add(new RefreshAction());
menuManager.add(new ExpandAction());
menuManager.add(new CollapseAction());
menuManager.add(new AddEntryAction());
menuManager.add(new RemoveEntryAction());
menuManager.add(new ModifyEntryAction());
/*
* 把这些功能加入到右键的Menu菜单中.
*/
Tree tree = treeViewer.getTree();
Menu menu = menuManager.createContextMenu(tree);
tree.setMenu(menu);
} /**
* 打开"菜单"对应的Action类
*/
private class OpenAction extends Action {
public OpenAction() {
setText("打开");
}
/**
* 继承自Action的方法,动作代码写此方法中
*/
//覆盖Action中的run()方法.
public void run() {
ITreeEntry obj = getSelTreeEntry();//getgetSelTreeEntry()得到当前节点
if (obj != null) {
//弹出一个这个节点名字的对话框.
MessageDialog.openInformation(null, null, obj.getName());
}
}
} /**
* 刷新对应的Action类.
*/
private class RefreshAction extends Action {
public RefreshAction() {
setText("刷新");
} //覆盖Action类中的run()方法,里面是调用的refresh()方法.
public void run() {
treeViewer.refresh();// 调用TreeViewer的刷新方法
}
} /**
* 展开当前结点的Action类
*/
private class ExpandAction extends Action {
public ExpandAction() {
setText("展开");
}
//重写run()方法
public void run() {
ITreeEntry obj = getSelTreeEntry();
if (obj != null) {
treeViewer.expandToLevel(obj, 1);
// 这个方法后面的数字是展开的层级数.这个地方设置成仅仅展开1个层级.
}
}
} /**
* 收缩当前结点的Action类
*/
private class CollapseAction extends Action {
public CollapseAction() {
setText("收缩");
}
//重写run()方法
public void run() {
ITreeEntry obj = getSelTreeEntry();
if (obj != null) {
treeViewer.collapseToLevel(obj, -1); // -1为将当前结点的所有子结点收缩
}
}
} /**
* 给当前结点增加一个子结点的Action类
*/
private class AddEntryAction extends Action {
public AddEntryAction() {
setText("增加");
}
@Override
public void run() {
ITreeEntry obj = getSelTreeEntry();
if (obj == null || obj instanceof People) {
return;
}
InputDialog dialog = new InputDialog(null, "给当前结点增加一个子结点", "输入名称", "请输入你要增加的节点的名字", null);
if (dialog.open() == InputDialog.OK) {// 如果单击OK按钮
String entryName = dialog.getValue(); // 得到Dialog输入值
/* 根据单击结点的不同类型生成相应的子结点 */
ITreeEntry newEntry = null;
if (obj instanceof Country) {
newEntry = new City(entryName);
} else if (obj instanceof City) {
newEntry = new People(entryName);
}
/* 在增加子结点之前将父结点展开 */
if (!treeViewer.getExpandedState(obj)) {
treeViewer.expandToLevel(obj, 1);
}
treeViewer.add(obj, newEntry);// 增加结点
}
}
} /**
* 删除结点的Action类
*/
private class RemoveEntryAction extends Action {
public RemoveEntryAction() {
setText("删除");
}
@Override
public void run() {
ITreeEntry obj = getSelTreeEntry();
if (obj == null) {
return;
}
treeViewer.remove(obj);
}
} /**
* 修改结点名称的Action类
*/
private class ModifyEntryAction extends Action {
public ModifyEntryAction() {
setText("修改");
}
@Override
public void run() {
ITreeEntry obj = getSelTreeEntry();
if (obj == null) {
return;
}
InputDialog dialog = new InputDialog(null, "修改结点", "输入新名称", obj.getName(), null);
if (dialog.open() == InputDialog.OK) {
String entryName = dialog.getValue();//得到对话框中的值.
obj.setName(entryName);//给这个节点设置成得到的对话框中的名字.
treeViewer.refresh(obj); // 刷新结点
}
}
}
/**
* 这个方法是自定义的方法,这个方法的作用就是得到当前选择的节点.
*/
private ITreeEntry getSelTreeEntry() {
IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
ITreeEntry treeEntry = (ITreeEntry) (selection.getFirstElement());
return treeEntry;
}
}

TreeViewer.java的实例

 public class TreeViewer1 {
public static void main(String[] args) {
TreeViewer1 window = new TreeViewer1();
window.open();
} //定义这个open()方法.就是创建一个典型的SWT程序的步骤
public void open(){
//1.Display负责管理一实现循环和控制UI线程和其他线程之间的通信
final Display display = new Display();
//2.创建一个或者多个Shell(shell是程序的主窗口)
final Shell shell = new Shell();
//3.设置shell的布局.
shell.setSize(200, 300);
//设置shell的布局为FillLayout
shell.setLayout(new FillLayout());
shell.setText("TreeViewer的第一个例子"); Composite c = new Composite(shell, SWT.NONE);
c.setLayout(new FillLayout());
TreeViewer treeViewer = new TreeViewer(c, SWT.BORDER);
treeViewer.setContentProvider(new TreeViewerContentProvider());
treeViewer.setLabelProvider(new TreeViewerLableProvider());
// 和TableViewer一样,数据的入口也是setInput方法
Object inputObj = DataFactory.createTreeData();
treeViewer.setInput(inputObj); /*
//调用自定义的方法创建表格
createTableViewer(shell);
//4.设定内容器
tableviewer.setContentProvider(new TableViewerContentProvider());
//5.设定标签器
tableviewer.setLabelProvider(new TableViewerLabelProvider());
//6.用setInput输入数据(把PeopleFactory产生的List集合传进来)
tableviewer.setInput(PeopleFactory.getPeoples());
*/ //7.创建Shell中的组件(这个例子中没有加入组件,只有一个空窗口)
shell.open();
//8.写一个时间转发循环
while(!shell.isDisposed()){//如果主窗口没有关闭,则一直循环
//dispose 是"处理,处置,毁掉"的意思
if(!display.readAndDispatch()){//// 如果display不忙
display.sleep();// display休眠
}
}
}
}

TreeViewer1.java的运行结果图

TreeViewer2.java

 public class TreeViewer2 {

     public static void main(String[] args) {
TreeViewer2 window = new TreeViewer2();
window.open();
} public void open() {
final Display display = new Display();
final Shell shell = new Shell();
shell.setSize(200, 300); shell.setLayout(new FillLayout());
Composite c = new Composite(shell, SWT.NONE);
c.setLayout(new FillLayout());
TreeViewer treeViewer = new TreeViewer(c, SWT.BORDER);
treeViewer.setContentProvider(new TreeViewerContentProvider());
treeViewer.setLabelProvider(new TreeViewerLableProvider());
Object inputObj = DataFactory.createTreeData();
//>>>>>>>>>>>>>相比于TreeViewer1.java增加的>>>>>>>>>>>>>>>>>>>>>>>>>
//生成一个ActionGroup对象
MyActionGroup actionGroup = new MyActionGroup(treeViewer);
// 调用fillContextMenu方法将按钮注入到菜单对象中
actionGroup.fillContextMenu(new MenuManager());
// --------------加入代码:END--------------------
treeViewer.setInput(inputObj);
// -----------------------------
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}

TreeViewer2.java的运行结果图:

上面的这个是<<Eclispe从入门到精通>>中第一版的代码,在第二版中对一些功能进行了一些改进.

该进在于"不同的结点显示不同的菜单".

树的"人"结点是没有子节点的.因此对于"人"这个节点来说,右键菜单中的"展开,收缩,增加"菜单项都没有任何意义,应该隐藏起来,再根据当前节点的类型决定要将哪些Action加入菜单中.按着这个思路将MyActionGroup类的fillContextMenu方法修改如下:

Eclipse中的TreeViewer类和ListViewer类的更多相关文章

  1. eclipse中运行出错:无法初始化主类的解决办法

    问题描述:eclipse中运行程序时,出现如下错误 解决办法: 出现此类:无法初始化主类有可能是因为eclipse中Java的版本与JDK的版本不匹配,我开始用的时候eclipse中用的是Java s ...

  2. 在Eclipse中生成接口的JUnit测试类

    在Spring相关应用中,我们经常使用“接口” + “实现类” 的形式,为了方便,使用Eclipse自动生成Junit测试类. 1. 类名-new-Other-java-Junit-Junit Tes ...

  3. eclipse中从数据库生成hibernate实体类

    为什么写这篇BLOG,是因为经常有同事或网友问起我hiberante实体类的生成问题.所以下次再有人问我可以省一堆的话了,其实这个真的是很简单.        现在hibernate在项目中的应用是越 ...

  4. eclipse中根据方法找到其实现类

    面向接口编程中,程序全是面向接口变成调用,在维护别人写的系统的时候怎么样快速定位当前根据接口调用的方法是哪个实体类实现的: Ctrl + T/f4(光标放在需要查看的方法上,然后按Ctrl+T或者F4 ...

  5. Eclipse中按CTRL键点击类不能进入

    是因为Eclipse或项目没有关联jdk,首先看window->preferences->java->Installed JREs,看是不是关联的你所安装的jdk,有的是关联的JRE ...

  6. Eclipse中Copy Qualified Name复制类全名解决办法

    Eclipse中用Copy Qualified Name复制类全名时总是这样的/struts1/src/me/edu/HelloAction.java很不方便可以这样解决下载下边插件解压到Eclips ...

  7. 如何在Eclipse中查看Android源码或者第三方组件包源码

    文章出处:http://blog.csdn.net/cjjky/article/details/6535426 在学习过程中如果经常阅读源码,理解程度会比较深,学习效率也会比较高,那么如何方便快捷的阅 ...

  8. Eclipse 中构建 Maven 项目的完整过程 - SpringBoot 项目

    进行以下步骤的前提是你已经安装好本地maven库和eclipse中的maven插件了(有的eclipse中已经集成了maven插件) 一.Maven项目的新建 1.鼠标右键---->New--- ...

  9. eclipse中使用lombok不生效

    eclipse中使用lombok,在实体类中添加@Data后,还是不能调用get.set方法.需要修改eclipse配置 1.将 lombok.jar 复制到eclipse.ini同级目录.下载的lo ...

随机推荐

  1. wcf的连接数

    </standardEndpoints> <behaviors> <serviceBehaviors> <behavior name="thrott ...

  2. 常规页生命周期(class0620)

    常规页声明周期阶段 阶段                   说明 页请求 开始 页初始化 加载 验证 回发事件处理 卸载 生命周期事件 页事件               典型使用

  3. 机器学习总结之逻辑回归Logistic Regression

    机器学习总结之逻辑回归Logistic Regression 逻辑回归logistic regression,虽然名字是回归,但是实际上它是处理分类问题的算法.简单的说回归问题和分类问题如下: 回归问 ...

  4. SQL中binary 和 varbinary的区别 blob

    binary 和 varbinary固定长度 (binary) 的或可变长度 (varbinary) 的 binary 数据类型. binary [ ( n ) ] 固定长度的 n 个字节二进制数据. ...

  5. 【转】Spark是基于内存的分布式计算引擎

    Spark是基于内存的分布式计算引擎,以处理的高效和稳定著称.然而在实际的应用开发过程中,开发者还是会遇到种种问题,其中一大类就是和性能相关.在本文中,笔者将结合自身实践,谈谈如何尽可能地提高应用程序 ...

  6. 让你系统认识flume及安装和使用flume1.5传输数据到hadoop2.2

    本文链接: http://www.aboutyun.com/thread-7949-1-1.html 问题导读:1.什么是flume?2.如何安装flume?3.flume的配置文件与其它软件有什么不 ...

  7. 【noip模拟】考试总结

    今天睡了14个小时啊 把一星期的觉都补回来了 要不是被叫醒了 我肯定还在睡觉- - 其实现在还想睡... 集训真是伤身啊 感觉再睡就要睡成sb了 鉴于昨天被完虐(真·完虐 怒垫底) 来写篇总结 得分: ...

  8. Apache Hadoop 源码阅读

    总之一句话,这些都是hadoop-2.2.0的源代码里有的.也就是不光只是懂理论,编程最重要,还是基本功要扎实啊.... 在hadoop-2.2.0的源码里,按Ctrl + Shift + T . 跳 ...

  9. hdu 2716 Message Decowding

    Message Decowding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  10. SQLite使用教程4 附加数据库

    http://www.runoob.com/sqlite/sqlite-attach-database.html SQLite 附加数据库 假设这样一种情况,当在同一时间有多个数据库可用,您想使用其中 ...