1、内容提供者是让当前的app的数据可以让其他应用访问,其他应该可以通过内容提供者访问当前app的数据库

contentProvider的主要目的是提供一个开发的接口,让其他的应该能够访问当前应用的数据

2、建立的操作类必须继承自定义的内容提供者必须继承ContentProvider

3、创建的创建的PersonProvider必须在应用的主包名和主包名的子目录下,现在应用的主包名是 package="test.weiyuan.sqllite1"

4、内容提供者编写好之后需要在清单文件中进行注册,Android的四大组件都需要在清单文件中进行注册,因为provide是让外部的应用通过provide能够访问当前应用的数据,所以需要指明provide的访问路径   android:authorities,一般采用包名+provider的名字的形式

我们看下清单配置文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.weiyuan.sqllite1" > <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
//对内容提供者进行注册
<provider
android:authorities="test.weiyuan.sqllite1.PersonProvider"
android:name=".PersonProvider"
android:exported="true"> </provider>
<activity
android:name=".MyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

上面的三个属性必须必须填写,其中Android:exported为true表示该数据允许外面的程序访问,不要忘记填写

整个程序的代码框架也是采用mvc的架构

我们来一一分析

DbOpenHelper 类:
package dB;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast; public class DbOpenHelper extends SQLiteOpenHelper
{ public DbOpenHelper(Context context) { super(context, "wy.db", null, 2);
} @Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE person(personid integer primary key autoincrement, name varchar(20), phone VARCHAR(12) NULL)"); } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

业务库操作接口类:

可以有下面的两种方式操作数据库:

/**
* 文件名:PersonService.java
* 版权:版权所有 (C) 中国电科30所三部
* 描述:
* 修改人: wei.yuan
* 修改时间:2015/1/9
* 修改内容:新增
*/
package service; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log; import java.util.ArrayList;
import java.util.List; import dB.DbOpenHelper;
import domain.Person; /**
* 项目名称:SQLLite1
* 类描述:
* 创建人:wei.yuan
* 创建时间:2015/1/9 11:08
* 修改人:wei.yuan
* 修改时间:2015/1/9 11:08
* 修改备注:
* 版权:版权所有 (C) 中国电科30所三部
*/
public class PersonService {
private DbOpenHelper dbOpenHelper; public PersonService(Context context) {
this.dbOpenHelper = new DbOpenHelper(context);
}
public void save(Person person){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("insert into person(name, phone) values(?,?)",
new Object[]{person.getName(), person.getPhone()});
}
/**
* 删除记录
* @param name 记录ID
*/
public void delete(String name,String phone){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("delete from person where name=? and phone=?", new Object[]{name,phone});
}
/**
* 更新记录
* @param person
*/
public void update(Person person,String name,String phone){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("update person set name=?,phone=? where name=? and phone=?",
new Object[]{person.getName(), person.getPhone(),name,phone});
}
/**
* 查询记录
* @param name 记录ID
* @return
*/
public Person find(String name,String phone){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from person where name=? and phone = ?", new String[]{name,phone});
if(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("personid"));
String name1 = cursor.getString(cursor.getColumnIndex("name"));
String phone1 = cursor.getString(cursor.getColumnIndex("phone"));
return new Person( name1, phone1);
}
cursor.close();
return null;
}
/**
* 分页获取记录
* @param offset 跳过前面多少条记录
* @param maxResult 每页获取多少条记录
* @return
*/
public List<Person> getScrollData(int offset, int maxResult){
List<Person> persons = new ArrayList<Person>();
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from person order by personid asc limit ?,?",
new String[]{String.valueOf(offset), String.valueOf(maxResult)});
while(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("personid")); /*这里也可以写成
* String name = cursor.getString(1);
String phone = cursor.getString(2);
默认的表自带的id字段为0 ,name为第一个字段所有为1 ,phone为第二个字段为2*/
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
persons.add(new Person( name, phone));
}
cursor.close();
return persons;
} /**
* 获取记录总数
* @return
*/
public long getCount(){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select count(*) from person", null);
cursor.moveToFirst();
long result = cursor.getLong(0);//统计之后只有一个默认的字段,所以为0
cursor.close();
return result;
} /*使用 SimpleCursorAdapter加装数据的时候,创建的数据库表的主键必须是_id,
* 这里我们使用personid as _id,将创建表的主键personid变成_id
* 返回cursor对象的时候,千万不能关闭cursor对象:cursor.close();*/
public Cursor getScrollCursorData(int offset, int maxResult){
List<Person> persons = new ArrayList<Person>();
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select personid as _id,name,phone from person order by personid asc limit ?,?",
new String[]{String.valueOf(offset), String.valueOf(maxResult)}); return cursor;//返回cursor对象之前,千万不能关闭cursor对象cursor.close();
} }

方式二:

package service;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import java.util.ArrayList;
import java.util.List; import dB.DbOpenHelper;
import domain.Person; public class OtherPersonService {
private DbOpenHelper dbOpenHelper; public OtherPersonService(Context context) {
this.dbOpenHelper = new DbOpenHelper(context);
}
public void save(Person person){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name",person.getName());
values.put("phone",person.getPhone());
db.insert("person",null,values);
}
/**
* 删除记录
* @param name 记录ID
*/
public void delete(String name,String phone){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
/* db.execSQL("delete from person where name=? and phone=?", new Object[]{name,phone});*/
db.delete("person", "name=? and phone= ?", new String[]{name ,phone});
}
/**
* 更新记录
* @param person
*/
public void update(Person person,String name,String phone){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
/* db.execSQL("update person set name=?,phone=? where name=? and phone=?",
new Object[]{person.getName(), person.getPhone(),name,phone});*/
ContentValues values = new ContentValues();
values.put("name",person.getName());
values.put("phone",person.getPhone());
db.update("person",values,"name=? and phone=?",new String[]{name ,phone});
}
/**
* 查询记录
* @param name 记录ID
* @return
*/
public Person find(String name,String phone){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
/* Cursor cursor = db.rawQuery("select * from person where name=? and phone = ?", new String[]{name, phone});*/
Cursor cursor = db.query("person",null,"name=? and phone=?",new String[]{name,phone},null,null,null);
if(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("personid"));
String name1 = cursor.getString(cursor.getColumnIndex("name"));
String phone1 = cursor.getString(cursor.getColumnIndex("phone"));
return new Person( name1, phone1);
}
cursor.close();
return null;
}
/**
* 分页获取记录
* @param offset 跳过前面多少条记录
* @param maxResult 每页获取多少条记录
* @return
*/
public List<Person> getScrollData(int offset, int maxResult){
List<Person> persons = new ArrayList<Person>();
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
/* Cursor cursor = db.rawQuery("select * from person order by personid asc limit ?,?",*/
Cursor cursor = db.query("person",null,null,null,null,null,"personid asc",offset+ ","+ maxResult);
while(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("personid")); /*这里也可以写成
* String name = cursor.getString(1);
String phone = cursor.getString(2);
默认的表自带的id字段为0 ,name为第一个字段所有为1 ,phone为第二个字段为2*/
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
persons.add(new Person( name, phone));
}
cursor.close();
return persons;
} /**
* 获取记录总数
* @return
*/
public long getCount(){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
/*Cursor cursor = db.rawQuery("select count(*) from person", null);*/
Cursor cursor = db.query("person", new String[]{"count(*)"}, null, null, null, null, null);
cursor.moveToFirst();
long result = cursor.getLong(0);//统计之后只有一个默认的字段,所以为0
cursor.close();
return result;
} /*使用 SimpleCursorAdapter加装数据的时候,创建的数据库表的主键必须是_id,
* 这里我们使用personid as _id,将创建表的主键personid变成_id
* 返回cursor对象的时候,千万不能关闭cursor对象:cursor.close();*/
public Cursor getScrollCursorData(int offset, int maxResult){
List<Person> persons = new ArrayList<Person>();
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select personid as _id,name,phone from person order by personid asc limit ?,?",
new String[]{String.valueOf(offset), String.valueOf(maxResult)}); return cursor;//返回cursor对象之前,千万不能关闭cursor对象cursor.close();
}
}

javaBenn对象:

package domain;

public class Person
{ private String name;
private String phone; @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", phone='" + phone + '\'' +
'}';
} public Person(String name, String phone) {
this.name = name;
this.phone = phone;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
}
}

下面也是我们最为关键的内容提供者操作类:通过该类其他的应该就可以访问当前应用的数据,只要是业务操作,业务操作的异常都不要内部进行try catch捕获,而应该将业务操作的异常返回给调用者,当调用者进行业务操作的时候,如果遇到了异常就知道该业务操作是成功还是失败了,然后做出相应的处理。相当的关键

package test.weiyuan.sqllite1;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log; import dB.DbOpenHelper; /**
* Created by wei.yuan on 2015/6/3.
* 一定要在清单文件中对内容提供者进行注册
* PersonProvider必须在应用的包名目录下或者包名的子目录下
*/
public class PersonProvider extends ContentProvider { private DbOpenHelper dbOpenHelper;
//该类用于检测的外部应用输入的URL是否正确,如果正确返回码就是codePerson,不正确返回UriMatcher.NO_MATCH
private static final int codePerson = 1;
private static final int codePerson1 = 2;
//该类用于检测的外部应用输入的URL是否正确,如果不正确返回码就是new UriMatcher(UriMatcher.NO_MATCH)构造函数中的参数,这里是UriMatcher.NO_MATCH
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static
{
//这个url表示对整个person表进行操作,如果url匹配返回的值是codePerson
uriMatcher.addURI("test.weiyuan.sqllite1.PersonProvider","person",codePerson);
//这个url表示对person表中的某个记录进行操作,#表示的是数字,就是对应的person表中的某个记录
// android中#代表数字,*表示任意的字符,如果url匹配返回的值是codePerson1
uriMatcher.addURI("test.weiyuan.sqllite1.PersonProvider","person/#",codePerson1);
}
//onCreate()之后被调用一次,在调用的时候创建数据库,记得返回值为true
@Override
public boolean onCreate() {
dbOpenHelper = new DbOpenHelper(getContext());
return true;
} //查询数据表的数据
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
switch (uriMatcher.match(uri))
{
//更新整个表
case codePerson: return database.query("person",projection,selection,selectionArgs,null,null,sortOrder); //更新表中的某条记录
case codePerson1:
long row_id = ContentUris.parseId(uri);
String where = " personid="+row_id;
Log.i("weiyuan",""+row_id);
if (selection!=null&&!"".equals(selection.trim()))
{
where += "and "+selection;
}
return database.query("person",null,where,selectionArgs,null,null,sortOrder); default: //如果传人的url不正确,抛出一个异常提示用户
throw new IllegalArgumentException("this is a unkown url-->"+uri); } } //返回要操作数据的内容类型,如txt文本就是plain/text类型
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri))
{
//操作的是多条数据记录
case codePerson:
return "vnd.android.cursor.dir/person";
//操作的是单条数据
case codePerson1:
return "vnd.android.cursor.item/person";
default:
throw new IllegalArgumentException("this is a unkown url-->"+uri);
}
} //可以让外面的应用向内容提供者插入数据
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
switch (uriMatcher.match(uri))
{
case codePerson:
//这里如果values为空,就必须需要第二个参数有值这里为"name",如果values有值,第二个参数默认为空值
long rowid = database.insert("person",null,values);
// Uri insertUri = Uri.parse("context://test.weiyuan.providers.PersonProvider/person/"+rowid);可以使用下面的方法http://blog.csdn.net/feng88724/article/details/6331396
Uri insertUri = ContentUris.withAppendedId(uri,rowid);
if(database!=null)
{
database.close();
} return insertUri; default:
//如果传人的url不正确,抛出一个异常提示用户
if(database!=null)
{
database.close();
}
throw new IllegalArgumentException("this is a unkown url-->"+uri); } } //返回值int表示你删除了多少条记录
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
int num = 0;//删除的记录数目
switch (uriMatcher.match(uri))
{
//删除整个表
case codePerson: num =database.delete("preson",selection,selectionArgs);
if(database!=null)
{
database.close();
}
break;
//删除表中的某条记录
case codePerson1:
// 从url中要删除的记录的id
long row_id = ContentUris.parseId(uri);
String where = " personid="+ row_id;
//外面传递进行的条件
if (selection!=null&&!"".equals(selection.trim()))
{
where += "and "+selection;
}
num = database.delete("person",where,selectionArgs);
if(database!=null)
{
database.close();
}
break; default:
//如果传人的url不正确,抛出一个异常提示用户
throw new IllegalArgumentException("this is a unkown url-->"+uri); } return num;
} @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase();
switch (uriMatcher.match(uri))
{
//更新整个表
case codePerson: database.update("preson",values,selection,selectionArgs);
if(database!=null)
{
database.close();
}
break;
//更新表中的某条记录
case codePerson1:
long row_id = ContentUris.parseId(uri);
String where = " personid="+row_id;
Log.i("weiyuan",""+row_id);
if (selection!=null&&!"".equals(selection.trim()))
{
where += "and "+selection;
}
database.update("person",values,where,selectionArgs);
if(database!=null)
{
database.close();
}
break; default:
if(database!=null)
{
database.close();
}
//如果传人的url不正确,抛出一个异常提示用户
throw new IllegalArgumentException("this is a unkown url-->"+uri); }
return 0;
}
}

注意点2:

首先先让数据库这个app运行起来,现在我们在新建立一个app,在这个app中访问数据库app中的数据

我们使用测试工具类的办法来实现Android studio 中测试类必须继承AndroidTestCase,该类中的所有测试方法必须以test开头

package testSQLLite;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log; /**
* Created by wei.yuan on 2015/6/3.
*/
public class TestContextProvider extends AndroidTestCase {
final static String TAG ="weiyuan"; //测试插入数据
public void testInsert() throws Exception
{
//注意uri中的字符串一般是小写,下面写成大写不太规范,一般遵循包名+类名,注意conten不要写成context了
Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person");
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name","aonier");
values.put("phone","28");
// 下面 resolver.insert(uri,values)这个函数本质上是调用了PersonProvider这个内容提供者中的insert函数
resolver.insert(uri,values);
Log.i(TAG,"数据插入成功!"); } //删除数据
public void testDelete() throws Exception
{
Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person/1");
long id = ContentUris.parseId(uri);
Log.i(TAG,id+"");
ContentResolver resolver = getContext().getContentResolver(); resolver.delete(uri,null,null);
Log.i(TAG,"数据删除成功!");
} //更新表中的数据
public void testUpdate() throws Exception
{
Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person/1");
long id = ContentUris.parseId(uri); ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name","aonier");
values.put("phone","34");
resolver.update(uri,values,null,null);
Log.i(TAG, "数据更新成功!");
} //查询数据表的数据
public void testQuery() throws Exception
{
Uri uri = Uri.parse("content://test.weiyuan.sqllite1.PersonProvider/person"); ContentResolver resolver = getContext().getContentResolver();
Cursor cursor =resolver.query(uri, null, null, null, null);
while (cursor.moveToNext())
{
Log.i(TAG,"数据查询成功!"+cursor.getString(cursor.getColumnIndex("name"))); }
//加载自定义适配器的数据 } }

对应上面两种数据库的两种业务操作也可以使用测试类的方式进行测试:

package testSQLLite;

import android.test.AndroidTestCase;
import android.util.Log; import java.util.List; import dB.DbOpenHelper;
import domain.Person;
import service.OtherPersonService; public class OtherTestSQLLite extends AndroidTestCase {
final static String TAG ="weiyuan";
public void testCreateDb()
{
DbOpenHelper dbOpenHelper = new DbOpenHelper(getContext());
dbOpenHelper.getWritableDatabase();
Log.i(TAG,"数据库创建成功");
}
public void testSave() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
for(int i = 0;i<20;i++)
{
service.save(new Person("weiyuan"+i,"12345"+i));
}
Log.i(TAG,"数据保存成功");
} /*主要查找的是姓名和电话一起查找,只要满足了姓名和电话,才正确*/
public void testFind() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
Person person = service.find("weiyuan1","123451");
Log.i(TAG, person.toString());
Log.i(TAG,"数据查找成功"); } /*删除某个记录*/
public void testdelete() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
service.delete("weiyuan1","123451");
Log.i(TAG,"数据删除成功"); }
/*给新某个记录*/
public void testupdate() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
service.update(new Person("chendong","456789"),"weiyuan2","123452");
Log.i(TAG, "数据修改成功"); }
/*获得分页的数据*/
public void testScrollData() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
List<Person> persons = service.getScrollData(0, 5);
for(Person person : persons){
Log.i(TAG, person.toString());
} } public void testCount() throws Exception{
OtherPersonService service = new OtherPersonService(this.getContext());
long result = service.getCount();
Log.i(TAG, result+"");
} }
package testSQLLite;

import android.test.AndroidTestCase;
import android.util.Log;
import android.widget.Toast; import java.util.List; import dB.DbOpenHelper;
import domain.Person;
import service.PersonService; public class TestSQLLite extends AndroidTestCase {
final static String TAG ="weiyuan";
public void testCreateDb()
{
DbOpenHelper dbOpenHelper = new DbOpenHelper(getContext());
dbOpenHelper.getWritableDatabase();
Log.i(TAG,"数据库创建成功");
}
public void testSave() throws Exception{
PersonService service = new PersonService(this.getContext());
for(int i = 0;i<20;i++)
{
service.save(new Person("weiyuan"+i,"12345"+i));
}
Log.i(TAG,"数据保存成功");
} /*主要查找的是姓名和电话一起查找,只要满足了姓名和电话,才正确*/
public void testFind() throws Exception{
PersonService service = new PersonService(this.getContext());
Person person = service.find("chendong","456789");
Log.i(TAG, person.toString());
Log.i(TAG,"数据查找成功"); } /*删除某个记录*/
public void testdelete() throws Exception{
PersonService service = new PersonService(this.getContext());
service.delete("weiyuan1","123451");
Log.i(TAG,"数据删除成功"); }
/*给新某个记录*/
public void testupdate() throws Exception{
PersonService service = new PersonService(this.getContext());
service.update(new Person("chendong","456789"),"weiyuan2","123452");
Log.i(TAG, "数据修改成功"); }
/*获得分页的数据*/
public void testScrollData() throws Exception{
PersonService service = new PersonService(this.getContext());
List<Person> persons = service.getScrollData(0, 5);
for(Person person : persons){
Log.i(TAG, person.toString());
} } public void testCount() throws Exception{
PersonService service = new PersonService(this.getContext());
long result = service.getCount();
Log.i(TAG, result+"");
} }

最新文章

  1. out与ref的区别
  2. 使用Reaver对WPS加密网络进行暴力破解
  3. LinkedList的实现源码分析
  4. 我的CSS样式记事本(1)
  5. JS初学之-if else图片顺序及循环切换
  6. ios7 Cocos2dx 隐藏状态栏设置
  7. nginx 配置高并发
  8. ACMer
  9. sql_mode :(STRICT_TRANS_TABLES与STRICT_ALL_TABLES 区别)
  10. Dapper中使用存储分页。
  11. compilation 元素(ASP.NET 设置架构)
  12. 2、elasticsearch 的安装和插件的安装
  13. nginx配置之深入理解
  14. vue项目结构
  15. [ipsec][crypto] 什么是AEAD加密算法中的AAD 及aad length
  16. 使用Java API方式连接HDFS Client测试
  17. SWAP 简介
  18. [学习笔记]树套树 线段树套Splay
  19. wcf中的使用全双工通信(转)
  20. kubernetes1.9管中窥豹-CRD概念、使用场景及实例

热门文章

  1. 非阻塞赋值(Non-blocking Assignment)是个伪需求
  2. Kubernetes笔记(四):详解Namespace与资源限制ResourceQuota,LimitRange
  3. 【Linux】文件权限,ssh免密登录
  4. ASP.NET中AJAX的异步加载(Demo演示)
  5. Java 第十一届 蓝桥杯 省模拟赛 螺旋矩阵
  6. Java实现 蓝桥杯 基础练习 杨辉三角形
  7. Java实现 LeetCode 102 二叉树的层次遍历
  8. Java动态规划实现最短路径问题
  9. Java实现约瑟夫斯问题
  10. Linux学习初级篇-鸟哥的Linux私房菜 基础学习篇(第四版)