作者归档:℃冻番茄

linux下配置mongodb,无需编译!

1.认识及了解MongoDB

MongoDB 是一个面向集合的,模式自由的文档型数据库.

面向集合, 意思是数据被分组到若干集合,这些集合称作聚集(collections). 在数据库里每个聚集有一个唯一的名字,可以包含无限个文档. 聚集是RDBMS中表的同义词,区别是聚集不需要进行模式定义.
模式自由, 意思是数据库并不需要知道你将存入到聚集中的文档的任何结构信息.实际上,你可以在同一个聚集中存储不同结构的文档.
文档型, 意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 "[BSON]" 即 "Binary Serialized dOcument Notation."


集 文档数据库,键值对存储和关系型数据库的优点于一身.

MongoDB (名称来自"humongous") 是一个可扩展的,高性能,开源,模式自由,面向文档的数据库.使用C++编写,MongoDB特点:

    *     面向文档存储(类JSON数据模式简单而强大)

    *      动态查询

    *      全索引支持,扩展到内部对象和内嵌数组

    *      查询记录分析

    *      快速,就地更新

    *      高效存储二进制大对象 (比如照片和视频)

    *      复制和故障切换支持

    *     Auto- Sharding自动分片支持云级扩展性

    *      MapReduce 支持复杂聚合

    *      商业支持,培训和咨询

所 谓"面向集合"(Collenction-Orented),意思是数据被分组存储在数据集中, 被称为一个集合(Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库 (RDBMS)里的表(table),不同的是它不需要定义任何 模式(schema)。
模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同 结构的文件存储在同一个数据库里。
存储在集合中的文档,被存储为键-值对的形式。键用于唯一标 识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。我们称这种存储形式为 BSON(Binary Serialized dOcument Format)。

哪些公司在用MongoDB
sourceforge、github等。

MongoDB 有个缺点,存储的数据占用空间过大。

MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统 (丰富的功能)架起一座桥梁,集两者的优势于一身。根据官方网站的描述,Mongo 适合用于以下场景:

    * 网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
    * 缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。
    * 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
    * 高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对MapReduce引擎的内置支持。
    * 用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询。

自然,MongoDB的使用也会有 一些限制,例如它不适合:

    * 高度事务性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
    * 传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
    * 需要SQL的问题
Via:http://www.infoq.com/cn/news/2009/09/mongodb

性能

在 我的使用场合下,千万级别的文档对象,近10G的数据,对有索引的ID的查询不会比mysql慢,而对非索引字段的查询,则是全面胜出。 mysql实际无法胜任大数据量下任意字段的查询,而mongodb的查询性能实在让我惊讶。写入性能同样很令人满意,同样写入百万级别的数 据,mongodb比我以前试用过的couchdb要快得多,基本10分钟以下可以解决。补上一句,观察过程中mongodb都远算不上是CPU杀手。
Via:http://www.wentrue.net/blog/?p=772

2. 安装及配置
说明,MongoDB下载然后解压缩以后就可以直接使用了,不需要编译及安装。

在页面http://www.mongodb.org/display/DOCS/Downloads中找到适合于你所在操作系统的MongoDB版本。

[root@CentOS_Test_Server software]# wget http://downloads.mongodb.org/linux/mongodb-linux-i686-1.4.2.tgz

/home/software是存放软件的目录,把mongodb解压到其它的目录下

直接解压缩到目录/usr/local/webserver 下。
[root@CentOS_Test_Server software]# tar zxvf mongodb-linux-i686-1.4.2.tgz -C /usr/local/webserver/

[root@CentOS_Test_Server webserver]# ls
eaccelerator_cache  mongodb-linux-i686-1.4.2  mysql  nginx  php  squid

将目录改名,方便以后使用方便。
[root@CentOS_Test_Server webserver]# mv mongodb-linux-i686-1.4.2/ mongodb

[root@CentOS_Test_Server software]# cd /usr/local/webserver/mongodb
[root@CentOS_Test_Server mongodb]# ls
bin  GNU-AGPL-3.0  include  lib  README  THIRD-PARTY-NOTICES

直接查看README文件的内容,里面的说明对使用MongoDB也会很有帮助。
[root@CentOS_Test_Server mongodb]# more README

MongoDB
=======

Welcome to MongoDB!

Package Contents
—————-

  bin/mongod            – MongoDB server
  bin/mongo             – MongoDB client

  bin/mongodump         – MongoDB dump tool – for backups, snapshots, etc..
  bin/mongorestore      – MongoDB restore a dump
  bin/mongoexport       – Export a single collection to test (json,csv)
  bin/mongoimportjson   – Import a json file into a collection

  bin/mongofiles        – Utility for putting and getting files from MongoDB gridfs

Useful Resources
—————-

 MongoDB Website

 * http://www.mongodb.org/

Documentation

 * http://www.mongodb.org/display/DOCS/Documentation

 MongoDB Maillists & IRC

 * http://www.mongodb.org/display/DOCS/Community

如果直接输入命令./mongod,则 MongoDB的数据直接保存在/data/db目录(windows操作系统下是c:\data\db目录), 默认监听在27017端口。
如 果你启动MongoDB时没有指定任何参数,同时目录/data/db也不存在,则会报错。

[root@CentOS_Test_Server bin]# ./mongod –help | grep fork
  –fork                    fork server process
[root@CentOS_Test_Server bin]# ./mongod –help | grep dbpath
  –dbpath arg (=/data/db/) directory for datafiles
                            dbpath
  –fastsync            indicate that this instance is starting from a dbpath
[root@CentOS_Test_Server bin]# ./mongod –help | grep port
  –port arg                specify port number
  –source arg          when slave: specify master as <server:port>

运 行./mongod –help命令时mongodb提示了一下,也就是32位操作系统只支持最大2G的文件,如果你的应用中数据量很大,超过了2G,推荐安装64位的操作 系统。2Gb or Not 2Gb – File limits说明 了为什么32位操作系统只支持最大2G的文件。

[root@CentOS_Test_Server bin]# ./mongod –help | more

** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see http://blog.mongodb.org/post/137788967/32-bit-limitations for more

创建目录保存MongoDB数据的目录。
[root@CentOS_Test_Server bin]# mkdir /home/mongodb_data

启动MongoDB

[root@CentOS_Test_Server bin]# ./mongod –fork –dbpath=/home/mongodb_data –logpath /home/mongodb_data/mongodb.log –logappend
all output going to: /home/mongodb_data/mongodb.log
forked process: 3799

[root@CentOS_Test_Server bin]# ps aux | grep mongo
root      3799  0.0  0.7  59032  2008 ?        Ssl  16:59   0:00 ./mongod –fork –dbpath=/home/mongodb_data –logpath /home/mongodb_data/mongodb.log –logappend
root      3825  0.0  0.2   3920   628 pts/1    S+   17:00   0:00 grep mongo

[root@CentOS_Test_Server bin]# netstat -antl | grep 27017
tcp        0      0 0.0.0.0:27017               0.0.0.0:*                   LISTEN

停止 MongoDB的进程时不能用kill -9,而最好用kill -15,否则会导致出现问题。

Sending a Unix INT or TERM signal

You can cleanly stop mongod using a SIGINT or SIGTERM signal on Unix-like systems. Either ^C, "kill -2 PID," or kill -15 PID will work.

Please note that sending a KILL signal kill -9 will probably cause damage as mongod will not be able to cleanly exit.  (In such a scenario, run the repairDatabase command.)


同时会自动启动一个端口为28017的服务,此服务用于监控MongoDB的状态
[root@CentOS_Test_Server bin]# netstat -a | grep 28017
tcp        0      0 *:28017                     *:*                         LISTEN

用curl可以在启动MongoDB所在的服务器上面直接访问, 如果想从其它的访问访问此服务,则必须在防火墙上开放28017端口。
[root@CentOS_Test_Server bin]# curl localhost:28017
<html><head><title>mongodb CentOS_Test_Server:27017 </title></head><body><h2>mongodb CentOS_Test_Server:27017 </h2><p>
<pre>db version v1.4.2, pdfile version 4.5
git hash: 53749fc2d547a3139fcf169d84d58442778ea4b0
sys info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37
…..

我在服务器上打开了28017端口,不知道为什么 在其它的电脑上面输入地址http://192.168.1.111:28017/无法访问,暂时不知道是什么原因。
[root@CentOS_Test_Server bin]# iptables -A RH-Firewall-1-INPUT -p tcp -m state –state NEW -m tcp –dport 28017 -j ACCEPT
[root@CentOS_Test_Server bin]# /etc/init.d/iptables save
Saving firewall rules to /etc/sysconfig/iptables:          [  OK  ]

更多MongoDB启动的问题,请移步 Starting and Stopping Mongo,http://www.mongodb.org/display/DOCS/Starting+and+Stopping+Mongo

3. 测试
[root@CentOS_Test_Server bin]# ls
运行MongoDB下面bin目录下的mongo命 令,就可以进入MongoDB的shell界面了,跟MySQL有点类似,输入命令help,其它的看帮助基本上就明白了。
mongo  mongod  mongodump  mongoexport  mongofiles  mongoimport  mongorestore  mongos  mongosniff  mongostat
[root@CentOS_Test_Server bin]# ./mongo
MongoDB shell version: 1.4.2
url: test
connecting to: test
type "help" for help
> help
HELP
        show dbs                     show database names
        show collections             show collections in current database
        show users                   show users in current database
        show profile                 show most recent system.profile entries with time >= 1ms
        use <db name>                set curent database to <db name>
        db.help()                    help on DB methods
        db.foo.help()                help on collection methods
        db.foo.find()                list objects in collection foo
        db.foo.find( { a : 1 } )     list objects in foo where a == 1
        it                           result of the last line evaluated; use to further iterate

在MongoDB中,在使用Database或Collection前不需要提前创建,在使用的过程中会 自动创建。
更多的有关信息请移步MongoDB Tutorial

a.测试一
我们来测试一下就明白了
> use recommender //
在此之前我可从来没有创建过数据库recommender
> a={name: "caihuafeng"} //也就是json对象,大家看起来是不是非常熟悉
{ "name" : "caihuafeng" }
> b={website: "1616.net"}
{ "website" : "1616.net" }
> db.data.save(a) //
在此之前我可没有创建过表data,在数据库recommender的表data中保存数据a,可以理解为往MySQL的表data中添加一条记录
> db.data.save(b) //在数据库recommender的表data中保存数据b,可以理解为往MySQL的表data中添加一条记录
> db.data.find()   //显示数据库recommender的表data中的所有数据
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
> show collections //显示数据库recommender中的所有表(collection在这里相当于MySQL中的表)
data
system.indexes //这个表是自动创建的

显示数据库recommender中website为1616.net的记录,相当于MySQL中的 SELECT * FROM data WHERE website='1616.net';
> db.data.find({website:"1616.net"})
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }

显示 数据库recommender中name为caihuafeng的记录,相当于MySQL中的SELECT * FROM data WHEREname ='caihuafeng';
> db.data.find({name:"caihuafeng"})
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }

MongoDB 比其它的关系型数据库更加灵活,因为每一行的记录都可以有不同的结构,而且表的结构根本上不需要提前创建,灵活极了。

b.测试二
发现就是在写js代码,然后跟数据库结合起来了。
> for (var i = 1; i <= 10; i++) db.data.save({"x":6, "name":"caihuafeng" + i});
> db.data.find();
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1" }
{ "_id" : ObjectId("4bee804ba23d558eb6687118"), "x" : 6, "name" : "caihuafeng2" }
{ "_id" : ObjectId("4bee804ba23d558eb6687119"), "x" : 6, "name" : "caihuafeng3" }
{ "_id" : ObjectId("4bee804ba23d558eb668711a"), "x" : 6, "name" : "caihuafeng4" }
{ "_id" : ObjectId("4bee804ba23d558eb668711b"), "x" : 6, "name" : "caihuafeng5" }
{ "_id" : ObjectId("4bee804ba23d558eb668711c"), "x" : 6, "name" : "caihuafeng6" }
{ "_id" : ObjectId("4bee804ba23d558eb668711d"), "x" : 6, "name" : "caihuafeng7" }
{ "_id" : ObjectId("4bee804ba23d558eb668711e"), "x" : 6, "name" : "caihuafeng8" }
{ "_id" : ObjectId("4bee804ba23d558eb668711f"), "x" : 6, "name" : "caihuafeng9" }
{ "_id" : ObjectId("4bee804ba23d558eb6687120"), "x" : 6, "name" : "caihuafeng10" }

> var cursor = db.data.find();
> while (cursor.hasNext()) {print(tojson(cursor.next()))};
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{
        "_id" : ObjectId("4bee804ba23d558eb6687117"),
        "x" : 6,
        "name" : "caihuafeng1"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687118"),
        "x" : 6,
        "name" : "caihuafeng2"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687119"),
        "x" : 6,
        "name" : "caihuafeng3"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711a"),
        "x" : 6,
        "name" : "caihuafeng4"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711b"),
        "x" : 6,
        "name" : "caihuafeng5"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711c"),
        "x" : 6,
        "name" : "caihuafeng6"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711d"),
        "x" : 6,
        "name" : "caihuafeng7"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711e"),
        "x" : 6,
        "name" : "caihuafeng8"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711f"),
        "x" : 6,
        "name" : "caihuafeng9"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687120"),
        "x" : 6,
        "name" : "caihuafeng10"
}

> db.data.find({x:6}, {name:true}).forEach(function(x) {print(tojson(x));});
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "name" : "caihuafeng1" }
{ "_id" : ObjectId("4bee804ba23d558eb6687118"), "name" : "caihuafeng2" }
{ "_id" : ObjectId("4bee804ba23d558eb6687119"), "name" : "caihuafeng3" }
{ "_id" : ObjectId("4bee804ba23d558eb668711a"), "name" : "caihuafeng4" }
{ "_id" : ObjectId("4bee804ba23d558eb668711b"), "name" : "caihuafeng5" }
{ "_id" : ObjectId("4bee804ba23d558eb668711c"), "name" : "caihuafeng6" }
{ "_id" : ObjectId("4bee804ba23d558eb668711d"), "name" : "caihuafeng7" }
{ "_id" : ObjectId("4bee804ba23d558eb668711e"), "name" : "caihuafeng8" }
{ "_id" : ObjectId("4bee804ba23d558eb668711f"), "name" : "caihuafeng9" }
{ "_id" : ObjectId("4bee804ba23d558eb6687120"), "name" : "caihuafeng10" }

只取前3条记录,跟MySQL中的limit是类似的意思。
> db.data.find().limit(3);
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1"

4.MongoDB的主从复制(Master/Slave)配置及测试

主从复制有什么用呢? 比如,在两台服务器上分别部署了MongoDB,当一台出现了问题以后,另外一台可以接管服务,同时也起备份的作用。
MongoDB supports replication of data between servers for failover and redundancy.

MongoDB支持4种形式的复制,推荐用master/slave复制
    *  Master-Slave Replication
    * Replica Pairs
    * Replica Sets
    * Limited Master-Master Replication

All else being equal, master/slave is recommended for MongoDB version 1.4.

与Master及Slave相关的帮助选项
[root@CentOS_Test_Server bin]# ./mongod –help | grep master
  –master              master mode
  –source arg          when slave: specify master as <server:port>
                        master ops to slave

[root@CentOS_Test_Server bin]# ./mongod –help | grep slave
  –slave               slave mode
  –source arg          when slave: specify master as <server:port>
  –only arg            when slave: specify a single database to replicate
  –slavedelay arg      specify delay (in seconds) to be used when applying
                        master ops to slave
  –autoresync          automatically resync if slave data is stale

启动MongoDB的Master服务
[root@CentOS_Test_Server bin]# ./mongod –fork –master –dbpath /home/masterdb/ –port 27018 –logpath /home/masterdb/mongodb.log –logappend
all output going to: /home/masterdb/mongodb.log
forked process: 11463
[root@CentOS_Test_Server bin]# ls /home/masterdb/
local.0  local.ns  mongodb.log  mongod.lock

启动MongoDB的Slave服务
[root@CentOS_Test_Server bin]# ./mongod –fork –slave –source localhost:27018 –autoresync –slavedelay 30 –dbpath /home/slavedb/ –port 27019 –logpath /home/slavedb/mongodb.log –logappend
all output going to: /home/slavedb/mongodb.log
forked process: 11848
[root@CentOS_Test_Server bin]# ls /home/slavedb/
local.0  local.ns  mongodb.log  mongod.lock  _tmp

测试主从复制的功能
登录到 MongoDB的Master服务,插入一条数据
[root@CentOS_Test_Server bin]# ./mongo localhost:27018
MongoDB shell version: 1.4.2
url: localhost:27018
connecting to: localhost:27018/test
type "help" for help
> use recommender
switched to db recommender
> db.data.insert({name: "caihuafeng"})
> db.data.find()
{ "_id" : ObjectId("4beedc31e0e4fff2ce0295f6"), "name" : "caihuafeng" }

登录MongoDB的Slave服务,我们发现刚才保存到Master里面的数据已经复制到Slave了,这正是我们要看到的效果。
[root@CentOS_Test_Server bin]# ./mongo localhost:27019
MongoDB shell version: 1.4.2
url: localhost:27019
connecting to: localhost:27019/test
type "help" for help
> use recommender
switched to db recommender
> db.data.find()
{ "_id" : ObjectId("4beedc31e0e4fff2ce0295f6"), "name" : "caihuafeng" }

我们再看一下Slave服务上面产生的同步日志(/home/slavedb/mongodb.log)
Sun May 16 01:39:29 repl: from host:localhost:27018
Sun May 16 01:39:29 resync: dropping database recommender
Sun May 16 01:39:29 resync: cloning database recommender to get an initial copy
Sun May 16 01:39:29 allocating new datafile /home/slavedb/recommender.ns, filling with zeroes…
Sun May 16 01:39:29 done allocating datafile /home/slavedb/recommender.ns, size: 16MB, took 0.451 secs
Sun May 16 01:39:29 allocating new datafile /home/slavedb/recommender.0, filling with zeroes…
Sun May 16 01:39:31 done allocating datafile /home/slavedb/recommender.0, size: 64MB, took 1.397 secs
Sun May 16 01:39:31 allocating new datafile /home/slavedb/recommender.1, filling with zeroes…
Sun May 16 01:39:31 building new index on { _id: 1 } for recommender.data
Sun May 16 01:39:31 Buildindex recommender.data idxNo:0 { name: "_id_", ns: "recommender.data", key: { _id: 1 } }

为 了让MongoDB的主从服务可以自动启动,可以把下面的两条命令加到/etc/rc.local中。
/usr/local/webserver/mongodb/bin/mongod –fork –master –dbpath /home/masterdb/ –port 27018 –logpath /home/masterdb/mongodb.log –logappend

/usr/local/webserver/mongodb/bin/mongod –fork –slave –source localhost:27018 –autoresync –slavedelay 30 –dbpath /home/slavedb/ –port 27019 –logpath /home/slavedb/mongodb.log –logappend

附:
Sun May 16 00:59:47 waiting for connections on port 27018
Sun May 16 00:59:47 web admin interface listening on port 28018

Sun May 16 01:12:27 waiting for connections on port 27019
Sun May 16 01:12:27 web admin interface listening on port 28019

mongodb的端口为27017时,相应的web admin监听的端口为28017
mongodb 的端口为27018时,相应的web admin监听的端口为28018
mongodb的端口为27019时,相应的web admin监听的端口为28019

找到了一个规律,就是web admin的端口就是将mongodb的端口的第二位改为8,猜测应该是这样的。

http://www.mongodb.org/display/DOCS/Master+Slave
http://www.mongodb.org/display/DOCS/Replication

5.MongoDB的Sharding功能
MongoDB的Sharding功能将在1.6版本中出现,将在2010年7月份发布。

MongoDB has been designed to scale horizontally via an auto-sharding architecture. Auto-sharding permits the development of large-scale data clusters that incorporate additional machines dynamically, automatically accomodate changes in load and data distribution, and ensure automated failover.

Sharding will be production-ready in MongoDB v1.6, estimated to be released in July, 2010. In the meantime, an alpha version of sharding is available in the 1.5.x development branch. Please see the limitations page for progress updates and current restrictions.

http://www.mongodb.org/display/DOCS/Sharding

6. 总结
在 写这篇文章以前,我没有用过MongoDB, 以前简单的看过一些MongoDB的资料,只是有点了解,今天自己动手安装测试了一下以后对MongoDB有了更加深入一点的了解,再学习几天基本上就可 以在项目中实际使用了,比如MongoDB的读写性能也有必要再测试一下,虽然已经有不少人已经测试过了,证明MongoDB的读写性能比MySQL高, 不过功能没有MySQL强。

其实TC的Table Database也能实现一些关系型数据库的功能,也是值得深入研究一下的,其实以前我简单的研究过。Tokyo Cabinet及Tokyo Tyrant的命令行接口

Table Database的特点是支持检索,支持多列字段,支持列索引,性能不如其它结构。
Table Database提供了类似RMDB的存储功能,一个主键可以有多个字段,例如,在RMDB中user表可能会有user_id、name和 password等字段,而在Table Database也提供这种支持。
Via:http://willko.javaeye.com/blog/506728

http://zhliji2.blogspot.com/2009/05/tokyo-cabinetdbm.html

下面的文章也比较精彩,对MongoDB感兴趣的可以看一看。
[译] MongoDB 入门教程:http://chenxiaoyu.org/blog/archives/242
http://www.fuchaoqun.com/2010/01/mongodb-in-action/
http://blog.chenlb.com/2010/05/mongodb-vs-mysql-query-performance.html
http://www.wentrue.net/blog/?p=772
http://www.mikespook.com/index.php/archives/524
http://hi.baidu.com/ywdblog/blog/item/44e02e9bfe5a87bfc8eaf425.html
http://www.infoq.com/cn/news/2009/09/mongodb
MongoDB 1.6 发布:
http://xiexiejiao.cn/database/mongodb-1-6-release.html
http://m.cnblogs.com/66952/1673308.html

MongoDB中文介绍:http://www.mongodb.org/display/DOCSCN/Home
MongoDB文档首 页:
http://www.mongodb.org/display/DOCS/Home

准备开始做房奴了

考虑再三还是决定回南昌买房,常州房价涨得太猛了。偏到高铁站那边去了,去年3400一平没买现在5200以上了,靠!

郁闷的是南昌最近开始城市改造,大量拆迁户拿政府8000一平方的补贴进入楼市买房,南昌房价又火起来了,看起来国家11条打压房价再次失败了,以后不相信政府了。还是早买早好,省得又白打工几年。

本来是想去北京东路附近买的,方便以后亲戚窜门,但是他妈的不是一般的贵,一个楼盘花了1万块预定,号不太好,一个小时后就剩1楼了,妈的!最后看了青云谱包家花园附近的房子,可是房子都只有一楼和顶楼,我的天啊,而且还一天一个价。后来没办法,只能订了城东一套房子。94平方44万,首付得3成,靠,已付了5万块的定金!这次中秋回南昌去交首付和办理贷款。

接下来的几年就要天天想着还贷了。最近几年不再关注楼市的事,太他妈的不是人干的事了。他妈的共产党你真心想把房价降下来就放剂猛药不就得了,听说欧洲不允许有空房,空房一定年限后国家收回分给没房的人住。现在国家只是控制控制银行贷款,但是炒房投机的人人,人家直接全额买可以么。靠!

搞定了qq机器人linux编译后内存泄漏问题

目前linux版本已正常工作,上周windows版本也存在内存泄漏问题,找了半天才发现是因为数组过界引的

另今天移值到linux平台,都是用gcc windows下正常 linux下就内存泄漏,怪事。。不过还好找到了问题所在。

另新加了一个程序自动从文本文件里读取验证码的功能,方便linux在nohup下运行,无需担心验证码输入的问题。

目前程序挂服务器上进行测试,如不稳定继续修改!

linux.jpg

花了些时间弄个QQ机器人

qq通信服务端是在myqq上二次开发,所以支持linux/windows双平台

主控程序采用php开发

主要的功能是:

查ip地址、查电话归属地、查天气预报、查pr值、在线翻译等都是些常用的功能

目前windows下正常,准备着手迁移至linux平台,还好机器人程序的主要库libcurl是跨平台的。

qq.jpg

转一篇暴笑笑话

           今天在公交车上,由于拥挤一男一女发生了碰撞。
    时髦女郎回头飞眼道:“你有病啊?”
    男子觉得莫名其妙回道:“你有药吗?”
    车上人窃笑!
    女子觉得生气回道:“你有精神病啊?”
    男子冷面对道:“你能治啊?”
    全车人爆笑!
    公交司机停车,趴在方向盘上大笑!
  
   这是珠江路上上班的朋友遇见的
     公交车上超挤,有一女人站在门口,
    从车后面挤过来一个GG要下车,
    跟那女的说了一句“让一下,下车”,那个女滴木有动。
    GG挤过去时就踩到她了。
    结果那女人好厉害的,不停的骂“神经病啊你!神经病啊你!~~”,还超大声,搞得全车都看呀。
    GG一直木有说话,下车时忍不了了,回头对那女人说,“复读机呀你!”
    全车人暴笑~!
    后边有几个搞笑的小孩,不停的伴演刚才的一幕,
    甲说“你神经病呀你!。。。。。乙说“你复读机呀你”。。。。。。 新浪乐居论坛:
    全车人暴笑~!
    后来,有个小MM也要下车,挤过去怯怯滴说“偶~偶~偶想下去,偶不是神经病~!”
    全车人再次暴笑~!
    那个女人木有说话,可是从边上飘来一句话“你是不是没电了”
    全车人暴笑不止~!

windows下安装mongodb及php驱动

mongodb是nosql的典型了,采用是json类似的存储格式

mongodb官网下载windows平台下的服务端: http://www.mongodb.org/downloads

mongodb的php驱动:http://github.com/mongodb/mongo-php-driver/downloads

mongodb下载后,解压到D盘,最终地址是:D:\mongodb\bin

php驱动 php_mongo.dll 解压至php的ext文件夹下,然后修改php.ini,添加 extension=php_mongo.dll

新建数据库存放文件夹  D:\mongodb\db

mongodb的启动:

在命令行输入  D:\mongodb\bin\mo\mongod –dbpath D:\mongodb\db

到这里,mongodb已启动,打开http://127.0.0.1:28017/ 可以看到mongodb运行情况

为了方便以后每次不必启动mongod,可以把mongod注册成windows服务

mongodb php使用方法:

3 用PHP操作Mongondb


简单列子 //这里采用默认连接本机的27017端口,当然你也可以连接远程主机如192.168.0.4:27017,如果端口是27017,端口可以省略
$m = new Mongo();

// 选择comedy数据库,如果以前没该数据库会自动创建,也可以用
$db = $m->comedy;

//选择comedy里面的collection集合,相当于RDBMS里面的表,也-可以使用
$collection = $db->collection;
$db->selectCollection("collection");

/* —– 添加一个元素 —–*/
$obj = array( "title" => "Calvin and Hobbes", "author" => "Bill Watterson" );
$collection->insert($obj);     //将$obj 添加到$collection 集合中

/* —– 添加另一个元素 —–*/
$obj = array(
"title" => "XKCD",
"online" => true
);
$collection->insert($obj);

$cursor = $collection->find();

//遍历所有集合中的文档
foreach ($cursor as $obj) {
echo $obj["title"] . "\n";
}   

//断开MongoDB连接
$m->close();

3.2 常用函数

		$query = array( "i" => 71 );    
$cursor = $collection->find( $query );      // 在$collectio集合中查找满足$query的文档    
 
while( $cursor->hasNext() ) {    
var_dump( $cursor->getNext() );    
}    
 
$collection -> findOne();            //返回$collection集合中第一个文档    
 
$collection -> count();              //返回$collection集合中文档的数量    
$coll->ensureIndex( array( "i" => 1 ) );  // 为i “这一列”加索引 降序排列    
$coll->ensureIndex( array( "i" => -1, "j" => 1 ) );  // 为i “这一列”加索引 降序排列 j升序

3.3 查询时,每个Object插入时都会自动生成一个独特的_id,它相当于RDBMS中的主键,用于查询时非常方便
如:

		<?php    
 
$person = array("name" => "joe");    
 
$people->insert($person);    
 
$joe = $people->findOne(array("_id" => $person['_id']));    
 
?>

昨天mysql生成了100w条文章数据(2G数据)做测试用

昨天写了个php程序,给mysql插入随机的文章数据,仿照真实文章,中文数据,主要是测试在100w级数量时查询上的优化及测试mysql内置的全文检索与其它类似全文检索引擎的差距等。总数据量:article 101w左右  user表10w左右,总计占用硬盘2G左右

今天开始测试在海量数据查询时的优化手段

  1. 测试添加索引对数据查询的影响:
    sql语句:select * from article as article order by time limit 10;
    没有对time字段建立索引时查询所花时间:31.237657s
    新建time字段的索引,花掉近二分钟,建立了111298条索引,没有建立完phpmyadmin就timeout了。
    建立time索引后,同样的sql语句执行只花了:0.380957s,不过time索引没有建完,但是时间相差不大;
    总结:在关键字段的索引上,建与不建速度相差近100倍!
     
  2. 测试limit在不同的基数上的影响:
    sql语句:select * from article as article order by id limit  0,10
    当limit的基数为0时【limit  0,10】,执行时间:0.001557s
    当limit的基数为20000时【limit  20000,10】,,执行时间:0.572288s
    当limit的基数为100000时,执行时间:2.793380s
    当limit的基数为50W 时,执行时间:14.444422s
    当limit的基数为100W时,执行时间:28.270054s
    总结:在海量数据中要想查找比较靠后的数据时,要注意limit的基数,因为随着数据量的加大,查找时间继续增长!在取比较后面的数据时,可以通过desc方式把数据反向查找,以减少对前段数据的扫描,让limit的基数越小越好!
     
  3. 测试field为*或是id对查询速度的影响:
    sql语句:select id from article as article order by id limit 100000,10
    为了数据更真实,所以通过limit让sql执行时间长些,以便更容易看出区别
    当field为id时,执行时间:2.617519s
    当field为*时,执行时间:2.867721s
    总结:由数量可见,二者在sql执行时间上相差并不大,但是限定field可以大幅度的减少内存开支
     
  4. 测试limit限定结果与between限定结果上的区别:
    当用limit          select * from article as article order by id limit 1000000,10      [31.163212s]
    当用between  select * from article as article where id between 1000000 and 1000010 order by id       [0.001433s]
    总结:between 限定上比limit快太多了,所以当在海量数据访问时,建议用between或是where把limit替换掉,但是between也有缺陷,如果id中间有断行或是中间部分id不读取的话,总读取的数量会少于预计数量!
     
  5. 测试left join对读取数据的影响
    user表,数据为100000条
    select id from article as article order by id limit 500000      [14.980397s]
    select article.id from article as article left join user as user on user.uid=article.uid order by article.id,user.username limit 500000      [60.488099s]
    总结:当数据量比较大时,用left join做连接是非常慢的,速度是查单表的4倍多,所以如果在大数据量的情况下,如果要实现刚实现用户表与文章表的连表功能,还是把全部的会员数据预先存入memcache等内存缓存中,10万条用户数据也不过5m不到,用户更新资料或登陆时,把用户的数据更新入memcache的指定用户中就ok了。这样速度就快了!


 

最后附上一截图

ssss.jpg
 

写了三个简单的算法,都是比较常用的

第一个是二分法查找,只能对有顺序的数组进行查找,速度应该是所有查找算法里最快的,

原理就是不停的做对折,以查找到目标!

第二个是冒泡排序,比较有名了,大学里c语言课必有的一个算法

第三个是从字符串中查找子串,也比较常用,以前用它做词频排序。

<?php
//二分法  $arr 数组,$k 要查找的值,$m 最小,$b最大
function dichotomy($arr,$k,$m=0,$b=0)
{
	$total=count($arr);
	if($total!=0 && $b==0) $b=$total;
	if($m<=$b){
		$avg=intval(($m+$b)/2);
		if($arr[$avg]==$k) return $avg;
		elseif($k<$arr[$avg]) return dichotomy($arr,$k,$m,$avg-1);
		else return dichotomy($arr,$k,$avg+1,$b);
	}
	return false;
}
echo "<hr>二分法查找<br>";
$arr=array(0,1,2,3,4,5,6,7,8,9,10);
var_dump(dichotomy($arr,1));


//冒泡排序
function bubblesort($arr)
{
	$total=count($arr);
	for($i=0;$i<$total-1;$i++){
		for($l=$i+1;$l<$total;$l++){
			if($arr[$i]>$arr[$l]){
				list($arr[$l],$arr[$i])=array($arr[$i],$arr[$l]);
			}
		}
	}
	return $arr;
}
echo "<hr>冒泡排序<br>";
$arr=array(1,100,23,434,22,12,3,5);
var_dump(bubblesort($arr));

//从字符串中搜索子串 $text 字符串,$str 要搜索的子串
function search($text,$str){
	$strLen=strlen($str);
	$textLen=strlen($text);
	for($i=0;$i<$textLen-$strLen;$i++){
		if(substr($text,$i,$strLen)==$str) return $i;
	}
	return false;
}
echo "<hr>字符串中搜索子串<br>";
$text="pdsofuapdoi3409729fhydish";
var_dump(search($text,"7"));
?>

比较实用的Java基本语法

 Java的基本符号(token)
  Java的单词符号有五种:关键字、标识符、常量、分隔符和操作符。
  Java的字符集
  Java 采用一种称为unicode的字符集,该字符集合是一种新的编码标准,与常见的ASCII码的区别在于:
  unicode使用16位二进制而不是8位来表示一个字符。
  unicode字符集中增加了许多非拉丁语字符。
  标识符
  Java标识符必须以字母,数字,美元符号"$",下划线"_"组成,标识符第一个字符不可用数字。
  Java语言对字母的大小写是敏感的,在语法中严格区分大小写。
  关键字
  关键字是为特定目的而保留的保留字,程序员不要将关键字作为自己的标识符。 Java的关键字有:
  abstract boolean break byte case catch char class continue do double else extends false
  find finally float for implements import instanceof int interface long native new null
  package private public return short static super switch synchronized this throw true try void while
  常量
  常量可分为整型常量,浮点数常量,字符常量,字符串常量和布尔常量。
  整型常量:可分为int型和long型两种,缺省为int型,long型数值后加L。 整型常量可用10、8和16进制表示。
  如:123(十进制) 052(八进制) 0x3c(十六进制)
  浮点数常量:有单精度和双精度之分,缺省为双精度,单精度在数值后加f。另外,浮点数常量也可用普通计数法和科学计数法来表示。
  如:1.23f 1.1E-2
  字符常量:用' '括起来的一个字符。如'a','H'。
  使用16位的unicode字符集。
  Java 语言可使用转义字符'\'来标记特殊字符。如'\n'表示换行符。
  字符串常量用" "包括,如"Hello World"。
  布尔常量只有两个值,true和false。
  分隔符
  分隔符起分隔单词符号的作用。包括分号";"、花括号"{}"和空白符号。
  Java的注释
  Java的注释有三种形式:
  单行注释
  如://Comment on one line
  多行注释
  如:/* Comment on one
  or more lines */
  文档注释
  如:/** Document
  Comment */
  Java的数据类型和变量
  Java的基本数据类型
  Java的基本数据类型有8种,见下表:
  数据类型 类别 宽度(位) 取值范围
  boolean 逻辑型 1 true/false
  char 文字型 16
  byte 整数类型 8 -27 ~ 27-1
  short 整数类型 16 -215 ~ 215-1
  int 整数类型 32 -231 ~ 231-1
  long 整数类型 64 -263 ~ 263-1
  float 浮点型 32
  double 浮点型 64
  Java的变量
  Java的变量在使用前必须声明。如 int radios, color;
  Java为所有基本数据类型的变量作了预定义(预设置的值)。如
  类型名 boolean char byte short int long float double
  预置值 false '\u0000' (byte)0 (short)0 0 0L 0.0f 0.0
  数据类型的转换
  Java是一种强类型的语言,在赋值和参数传递时,都要求类型的匹配。类型转换有三种情况:自动转换、强制转换和使用类的方法转换。
  自动转换:往往低精度类型到高精度类型能自动转换。
  如: byte b1=10, b2=20;
  int b3=b1+b2;
  强制转换:高精度类型到低精度类型必须强制转换。这时数据可能会丢失部分信息。
  如:char key=(char)(12+55) //变量key被赋值为unicode值为67的字符'c'
  方法转换:如
  String str = "123";
  int a = Integer.parseInt(str);
  使用Integer类的方法parseInt将String转换为对应的整数。
  Java编程的习惯约定
  为了提高程序的可读性,Sun公司推荐在Java编程时使用以下的习惯约定:
  类名(classes):有一个或若干个名词组成,开头大写,名词间的区分也用大写,其他小写。
  如:class AccountBook
  class ComplexVariable
  接口(Interfaces):规则同类名。
  如:Interface Account
  方法(methods): 由一个或多个动词组成,开头小写,动词间区分用大写,其他小写。
  如:balanceAccount()
  变量:小写字母开头,单词间用大写字母分隔
  如:currentCustomer
  常量:所有字母大写,单词间用下划线区分
  如:MAXIMUM_SIZE
  Java的操作符
  根据操作对象的个数操作符可分为一元、二元或三元操作符。根据操作符的功能,又可分为算术、逻辑、关系等操作符。
  算术操作符
  一元: + – ++ —
  二元: + – * / %
  值得注意的是 ++ 和– 操作符,
  如:int a,x=1,y=5;
  a = ++x;b=y++;
  此时a的值为2(先加1,后赋值),b的值为5(先赋值,后加1)。
  二元操作符两侧的操作对象数据类型不同时,先自动进行类型转换,再进行操作。

赋值操作符与复合赋值操作符
  可将 变量 = 变量 op 表达式
  写成 变量 op = 表达式
  如:x+=20 与 x=x+20 结果一致,但更简洁。
  注意:= 与 = = 的不同。
  位操作符和移位操作符
  位操作符
  &(按位与) |(按位或) ^(按位异或)
  移位操作符
  E<
  E>>n 右移n位,空位用原最高位的位值补足,相当于E/2
  E>>>n 右移n位,空位补0
  关系操作符
  关系操作符共六个:
  >(大于) >=(大于等于) <(小于)<=(小于等于) !=(不等于) = =(相等)
  关系操作符的结果为boolean型数据(true或false)。
  注:= = 操作符只有在比较双方均完全一致时,其值为true,如比较的是两个对象,即使两个对象的内容相同,结果也为false,
  只有这两个对象为同一对象时才为true。
  逻辑操作符
  逻辑操作符的操作对象和结果均为boolean型,共六个:
  !(逻辑非) && (逻辑与) ||(逻辑或)
  ^(逻辑并或) & (逻辑与) | (逻辑或)
  按位与'&'也可作为逻辑与使用,但未作优化,而'&&'操作符是经过优化的。对'|'操作符也类似。
  其他操作符
  条件操作符 E1?E2:E3
  表达式E1若成立,执行表达式E2,否则执行E3。
  逗号操作符
  ","可用于分隔语句。
  如 int x,y;
  for (x=0,y=0;x<10;x++) {…};
  操作符的优先级和结合规则
  优先级:
  一元 〉算术 〉移位 〉关系 〉按位 〉逻辑 〉三元 〉(复合)赋值 〉逗号
  结合规则:
  除一元、三元和赋值操作符是自右至左结合外,其他均自左至右结合。
  语句的分类
  Java语句按是否改变运行的状态可分为执行语句(如表达式语句)和非执行语句(如声明语句)。任何语句的末尾都以“;”结束。
  执行语句按其组成可分三类:
  空语句
  只有一个语句结束符“;” ,无任何内容。
  基本语句(单语句)
  独立的、完整的不能再分割为更小的可执行单元。
  复合语句(块语句)
  包含在{ }内的一条或若干条语句。
  Java的基本语句的结构可分为4类:
  (1)顺序结构语句 (2)分支语句 (3)循环语句 (4)例外处理语句
  后三种语句又称为流控制语句,我们将主要介绍分支语句和循环语句,而例外处理语句包括try、catch、finally以及throw语句。
  这些语句是Java所特有的。我们将在后面作专门的介绍。
  分支语句
  分支语句包括if-else, break, switch, return等语句。分支语句提供了一种控制机制,使得程序可以跳过一些语句,转去执行特定的语句。
  条件语句 if-else.
  if-else语句根据判定条件的真假来执行两种操作中的一种,其格式为:
  if (boolean-expression)
  statement1;
  else
  statement2;
  其中,要注意的有:
  布尔表达式boolean-expression是任意一个返回布尔型数据的表达式(这比C、C++的限制要严格)。
  每个单一的语句后都必须有分号。
  语句statement1, statement2可以是复合语句,这时要用花括号{}。{}外面不加分号。
  else子句是任选的。
  若布尔表达式的值为true,则程序执行statement1,否则执行statement2。
  if-else语句的一种特殊形式为:
  if (expression1){
  statement1
  } else if (expression2){
  statement2
  }……
  }else if (expressionN){
  statementN
  }
  else子句不能单独作为语句使用,它必须和if配对使用。else总是与离它最近的if配对。可以通过使用花括号{}来改变配对关系。
  例3.1: 比较两个数的大小,并按从小到大的次序输出。

public class CompareTwo{
  public static void main (String args[]){
  double d1=23.4;
  double d2=35.1;
  if (d2>=d1)
  System.out.println(d2+">="+d1);
  else
  System.out.println(d1+">="+d2);
  }
  }
  例3.2:判断某一年是否为闰年。
  闰年的条件是符合下面二者之一: ①能被4整除,但不能被100整除; ②能被400整除。
  public class LeapYear{
  public static void main (String args[]){
  int year=1989; //method1
  if ((year%4==0 && year0!=0) || (year@0==0))
  System.out.println(year+"is a leap year.");
  else
  System.out.println(year+"is not a leap year.");
  year=2000; //method2
  boolean leap;
  if (year%4 != 0)
  leap=false;
  else if (year0 != 0)
  leap=true;
  else if (year@0 != 0)
  leap=false;
  else
  leap=true;
  if(leap==true)
  System.out.println(year+" is a leap year.");
  else
  System.out.println(year+"is not a leap year.");
  }
  }
  该例中,方法1用一个逻辑表达式包含了所有的闰年条件,方法2使用了if-else语句的特殊形式。
  多分支语句switch
  switch语句是一种多分支选择语句,它可根据switch中表达式的值,来执行多个操作中的一个,它的一般格式如下:
  switch (expression){
  case value1: statement1;
  break;
  case value2: statement2;
  break;
  …………
  case valueN: statemendN;
  break;
  [default: defaultStatement;]
  }
  表达式expression可以返回任一简单类型的值(如整型、字符型),多分支语句把表达式返回的值与每个case子句中的值(一个常量)相比。
  如果匹配成功,则执行该case子句后的语句序列。
  default子句是任选的。当表达式的值与任一case子句中的值都不匹配时,程序执行default后面的语句。如果表达式的值与任一case子句
  中的值都不匹配且没有default子句,则程序不做任何操作,直接跳出switch语句。
  break语句用来在执行完一个case分支后,使程序跳出switch语句,即终止switch语句的执行。
  switch语句的功能可以用if-else来实现,但在某些情况下,使用switch语句更简炼,且程序的执行效率提高。
  例3.3 根据考试成绩的等级打印出百分制分数段。
  public class GradeLevel {
  public static void main(String args[]){
  System.out.println("\nOutPut is:");
  char grade='C'; //normal use
  switch (grade){
  case 'A': System.out.println(grade+"is 85~100");
  break;
  case 'B': System.out.println(grade+"is 70~84");
  break;
  case 'C': System.out.println(grade+"is 60~69");
  break;
  case 'D': System.out.println(grade+"is <60");
  break;
  default: System.out.println("inputerror");
  }
  }
  }
  break语句
  在switch语中,break语句用来终止switch语句的执行。使程序在switch语句后的第一个语句开始执行。
  在Java中,可以为每个代码块加一个括号。一个代码块通常是用花括号{}括起来的一段代码。加标号的格式如下:
  BlockLabel: {codeBlock}
  break语句的第二种使用情况就是跳出它所指定的块,并从紧跟该块的第一条语句处执行。其格式为: break BlockLabel;
  例如:
  a: {…… //标记代码块a
  b: {…… //标记代码块b
  c: {…… //标记代码块c
  break a;
  ……//will not be executed
  }
  ……//will not be executed
  }
  ……//will not be executed
  }
  …… //execute from here
  与C、C++不同, Java中没有goto语句来实现任意的跳转, 因为goto语句破坏程序的可读性, 而且影响编译的优化。Java用break来实现goto语句所特有的一些功能。
  返回语句return
  return语句用于从当前执行的方法中退出, 并返回到调用该方法的语句处继续程序的执行。返回语句有两种格式:
  return expression
  返回一个值给调用该方法的语句, 返回值的数据类型必须与方法声明中的返回值类型一致。可以使用强制类型转换来使类型一致。
  return
  当方法说明中用void声明返回类型为空时, 可以使用这种格式, 它不返回任何值。不带参数的return语句有时可省略。
  return语句通常用在一个方法体的最后。
  循环语句
  循环语句包括 while, do-while, for, continue 等语句。循环语句的作用是反复执行一段代码,直到满足循环终止条件为止,
  一个循环一般应包括四部分内容:
  初始化部分(initialization): 用来设置循环的一些初始条件,计数器清零等。
  循环体部分(body): 这是反复循环的一段代码,可以是单一的一条语句,也可以是复合语句。
  迭代部分(iteration): 这是在当前循环结束,下一次循环开始前执行的语句,常常用来使计数器加1或减1。
  终止部分(termination): 通常是一个布尔表达式,每一次循环要对该表达式求值,以验证是否满足循环终止条件。
  下面分别介绍Java中的while语句,do-while语句和for语句。
  while语句
  while语句的一般格式为:
  [初始化]
  while (条件表达式E){
  语句S; //循环体
  }
  当条件表达式E的值为true时,循环执行花括号中的语句S。S中包括迭代部分。
  while语句首先计算条件表达式E是否成立,当条件成立(true)时,才去执行循环中的语句。所以有可能循环体一次也不执行。
  do-while语句
  do-while语句的一般格式为:
  [初始化]
  do {
  语句S; //循环体
  } while (条件表达式E);
  do-while语句首先执行循环体, 然后再计算终止条件, 若结果为true, 则循环执行语句S, 直到条件表达式E的结果为false。
  与while语句不同的是, do-while语句的循环体至少执行一次。

 

 for语句
  for语句的一般格式为:
  for (初始表达式; 条件表达式; 迭代表达式) {
  语句S; //循环体
  }
  for语句执行时,首先执行初始化操作,然后判断终止条件是否满足,如果满足,则执行循环体中的语句,最后执行迭代部分。
  完成一次循环后,重新判断终止条件。
  可以在for语句的初始化部分声明变量,它的作用域为整个for语句。
  for语句通常用来执行循环次数确定的情况(如对数组元素进行操作)。
  在初始化部分和迭代部分可以使用逗号语句来分隔多个操作。例如:
  for (i=0,j=10; i<j; i++,j–) {
  ……
  }
  continue语句
  continue语句用来结束本次循环, 跳过循环体中下面尚未执行的语句, 接着进行终止条件的判断, 以决定是否继续循环。
  也可以用continue跳转到括号指明的外层循环中,这时的格式为
  continue outerLable;
  例3.4:下例分别用while、do-while和for语句实现累计求和。
  public class Sum{
  public static void main(String args[]){
  System.out.println("\n**while statement**");
  int n=10,sum=0; ∥initialization
  while (n>0){ ∥termination
  sum+=n; ∥body
  n–; ∥iteration
  }
  System.out.println("sum is"+sum);
  System.out.println("\n**do_while statement**");
  n=0; ∥initialization
  sum=0;
  do{
  sum+=n; ∥body
  n++; ∥iteration
  } while(n<=10); ∥termination
  System.out.println("sum is"+sum);
  System.out.println("\n**for statement**");
  sum=0;
  for (int i=1;i<=10;i++){
  sum+=i;
  }
  System.out.println("sum is"+sum);
  }
  }
  可以从中来比较这三种循环语句,从而在不同的场合选择合适的语句。
  数组
  数组是有序数据的集合, 数组中的每个元素具有相同的类型。数组名和下标可唯一地确定数组中的元素。数组可分为一维数组和多维数组。
  一维数组
  声明方式:
  type arrayName[];
  或 type[] arrayName;
  type可以是Java中任意的数据类型, arrayName为数组名。
  如: int intArray[];
  声明了一个名为intArray的整型数组, 数组中的每个元素为int型数据。
  Java在数组的声明中并不为数组元素分配内存, 因此 [ ] 中不用指出数组中元素个数, 即数组长度。
  在访问数组的任何元素之前,我们必须为它分配内存空间, 这可用new操作符, 其格式如下:
  arrayName = new type[arraySize];
  其中,arraySize指明数组的长度。
  如: intArray = new int[3]; 为该数组分配了3个int型整数所需的内存空间。
  通常, 这两部分可以合在一起, 格式如下:
  type arrayName[] = new type[arraySize];
  如: int intArray[] = new int[3];
  用new操作符为数组分配内存空间后,就可以引用数组中的每一个元素。数组元素的引用方式为: arrayName[index]
  其中: index为数组下标,它可以为整型常数或表达式。如a[3], b(i为整型), c[6*I]等。下标从0开始, 一直到数组的长度减1。
  对于上面例子中的intArray数组来说,它有3个元素,分别为:
  intArray[0], intArray[1], intArray[2]。(注意: 没有intArray[3]。)
  另外,与C、C++中不同,Java对数组元素要进行越界检查以保证安全性。同时,对于每个数组都有一个属性length指明它的长度。
  例如: intArray.length指明数组intArray的长度。
  数组的初始化
  对数组元素可以按照上述的例子进行赋值。也可以在定义数组的同时进行初始化。
  如: int a[]={1,2,3,4,5};
  用逗号(,)分隔数组的各个元素,系统自动为数组分配一定的内存空间。
  例3.5:数组的使用:
  public class ArrayTest{
  public static void main(String args[]){
  int i;
  int a[]=new int[5];
  for (i=0;i<5;i++)
  a=i;
  for (i=a.length-1;i>=0;i–)
  System.out.println("a["+i+"]="+a);
  }
  }
  多维数组
  与C、C++一样, Java中多维数组可被看作数组的数组。例如二维数组就可看成是一个特殊的一维数组, 该数组的每个元素又是一个一维数组。下面我们主要以二维数组为例来说明多维数组。
  二维数组的声明方式如下:
  type arrayName[][];
  如: int intArray[][];
  与一维数组一样,这时对数组元素也没有分配内存空间,同要使用运算符new来分配内存,然后才可以访问每个元素。
  对二维数组中每个元素,引用方式为:
  arrayName[index1][index2]
  其中index1、index2为下标, 可为整型常数或表达式, 如a[2][3]等。数组每一维的下标也都从0开始。
  在声明二维数组的同时也可对它进行初始化。
  如:int a[][]={{2,3},{1,5},{3,4}};
  定义了一个3×2的数组,并对每个元素赋值。
  数组的越界
  如果使用数组分量时,其下标超过规定的值,则会发生数组的越界。这时,虽然程序能通过编译,但在运行时会产生一个名为ArrayIndexOutOfBoundsException 的例外,所以编程时要注意检查数组下标。