util包
util包是java的工具包,即这里面包含了很多工具类:Arrays、Scanner、时间日期、集合...
util也是使用比较多的一个包,但java默认没有在程序里面引入,使用这个包里面的东西,需要单独导包。
比如使用Arrays 需要 import java.util.Arrays
如果使用这个包里面的类比较多, import java.util.*;
Data类
Date类表示是时间,精确到毫秒。 如果程序里面需要此时的时间,或者需要一个时间对象,可以实例化一个Date对象出,Date中包装时间。
构造方法:
new Date() --- > 无参的构造方法,表示此时时间。即将此时的日期时间封装成一个Date对象。这个时间是程序执行的系统的时间,即程序在哪执行 获得的就是哪个主机的时间。
new Date(String str) ---> 将一个字符串转成Date对象,(过时了)
str必须满足固定的格式: “yyyy/mm/dd hour:minute:second” 如果不是这个格式,编译可以通过, 但运行的时候报参数异常。
new Date(long x) ---> 将整数x转成一个时间对象。x代表了从1970-1-1 经过的毫秒数
代码:Date d = new Date(System.currentTimeMillis()); d代表此时时间
new Date(int y,int m ,int d) --->将整数y m d 转成一个date对象,
y代表y+1900代表年份 m+1代表月份 d天
普通方法:
toString() ---> 按照某个格式将date对象转成字符串。 星期 月份 日期 时分秒 年
toLocalString()---->按照本地的格式显示时间日期
get***() ---> 从时间日期对象中获取 年份、月份、。。。。
set***()------> 设置日期对象中的 年份、月份、。。。
getTime()----->将这个时间日期对象转成毫秒数,毫秒代码从1970-1-1,经过的毫秒数
如果有一个字符串需要转date对象,可以使用Date的构造方法,传入字符串,但这个方法过时了,不推荐使用,java推荐的是使用DateFormate对象来转换:
String str = "2012年12月12日";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年dd月mm日");
Date d = sdf.parse(str);
Calendar
Calendar也是一个时间日期类,但它是一个抽象类,只能使用它的子类或者他的静态的方法。Calendar里面提供了一个正好返回Calendar对象的静态方法。即如果需要一个Calendar对象则代码:
Calendar c = Calendar.getInstance();
创建一个Calendar对象后,这个对象里面包含了很多日期相关的信息,如果直接打印对象,数据不方便使用,所以如果需要什么数据,就是get方法从对象里面获取。
c.get( 字段名 ) 字段名是一个整数,Calendar提供了静态的字段。
c.set(字段名,值)
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 1999);
c.set(Calendar.MONTH,9-1);
c.set(Calendar.DATE,9);
c.add(字段名n,数字x) 将这个日期的某个字段加值
//用户输入年份 和月份 打印月历
Scanner sc = new Scanner(System.in);
System.out.println("请输入年份和月份:");
int year = sc.nextInt();
int month = sc.nextInt();
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONDAY, month-1);
c.set(Calendar.DATE, 1);
int x = c.get(Calendar.DAY_OF_WEEK);
//System.out.println(x);
System.out.println("日\t一\t二\t三\t四\t五\t六");
int n = c.getActualMaximum(Calendar.DAY_OF_MONTH);
int count = 0;
for(int i = 0;i < x-1;i++){
count++;
System.out.print("\t");
}
for(int i = 1;i <= n ;i++){
count++;
System.out.print(i + "\t");
if(count % 7 == 0){
System.out.println();
}
}
Random类
Math里面有个方法是 Math.random(), 这个方法只能随机0到1之间的小数,如果需要随机整数,则通过这个方法修改。
如果需要随机一个小写字母: (char)(Math.random()*26 + 97)
随机0到100之间的整数: (int)(Math.random()*100)
如果需要随机一个boolean类型的值?
Random类中提供了很多随机的方法:比如随机小数、随机整数、随机boolean类型 等等。。。
构造方法:
new Random() ----> 创建一个无参的Random对象,可以随机数据。
new Random(long n) ---> 创建一个Random对象,放入一个种子,种子的作用是保证程序多次运行,随机的数字 一样。
方法:
r.nextInt() ----> 随机一个整数,可能是任何一个整数,这个数可能很大,
如果是需要一个0-8之间的整数: r.nextInt() % 8
r.nextInt(int n) ----> 随机0到n之间的整数。
r.nextDouble() --->随机0到1之间的小数,与Math.random()功能一样。
r.nextBoolean() --->随机一个boolean类型
集合Collection
集合与数组一样,是一个存放数据的容器。但数组有缺点就是一旦数组创建后,它的长度就不能改变,即数组不能添加新位置,或者删除某个位置;数组还有一个缺点就是只能固定类型的数据,即数组定义的时候已经确定了数组只能放什么类型的数据。 集合正好弥补了数组的这两个缺点,即集合是一个长度没有限制,存放的数据也没有限制的容器。
java的3大集合: List Set Map (3个都是接口,即如果需要集合应该去实例化他们的实现类)
List 和 Set 来自同一个接口 Collection,数据是一个一个的向里面保存。 Map中的数据需要成对的向里面放入。
List中保存的数据是有顺序的,而且可以保存相同的数据。 Set中保存的数据是没有顺序的,而且不能保存相同的数据。
在List里面常用的有两个实现类: ArrayList LinkedList
ArrayList 以数组为基础,即他们保存的数据在内存中连续的,添加和删除会消耗时间,但它的查询很快。
LinkedList是以链表为基础,他们保存的数据在内存中不是连续的。查询很慢,但添加和删除数据很快
List
ArrayList
实现了List接口,继承了AbstractList。有序的且可以放重复元素的collection。以数组为基础,保存的元素在内存中的位置连续,查询比较快。 它不是线程安全的,即它的方法不是同步的。
构造方法:
new ArrayList() 创建一个ArrayList对象,初始容量为10.元素的长度为0.
new ArrayList(n) 创建一个初始容量为n的ArrayList对象。
功能方法:
list.size() : 返回集合的长度,即元素的个数
list.add(Object o) : 将对象o放入集合list中,o可以是任何数据(复合类型,如果放入基本类型,则会变成基本 类型的包装对象) add方法是将o放在集合的后面。
list.add(index,o) : 将对象o放入到集合的第index个位置,这个位置之前的内容和它后面的东西都整体向后移动 一位。
list.addAll(index,Collection c) : 将集合c中的数据全部取出,放入到index位置,后面的数据向后移动
list.clear() : 清除集合中的元素
list.clone() : 将这个集合克隆一个副本。是浅克隆,即集合中的元素没有被克隆。克隆出的集合和之前的集 合,他们的元素还是指向同一个位置
list.get(index) : 获取集合中的第index位置的元素,index从0开始,到list.size()-1结束,超过这个返回出现集合 下标越界异常。 从集合中获得的元素都是Object类型,如果确定这个元素的类型,可以使用强转
list.contains(o) : 判断集合list中是否包含了对象o,返回的是boolean类型。这个判断是使用对象的equals方法 判断的,即如果集合中10个元素,需要判断x是否在里面,则使用x的equals方法一个一个的去比 较里面的10个元素
list.indexOf(o) : 返回o在list中第一次出现的位置,如果list中没有o则返回-1. (list.lastInexOf())
list.isEmpty(): 判断此集合是否没有元素
list.remove(index) : 移除集合list中的第index位置上的元素,这个位置后面的元素都向前移动。返回的是被移 除的对象
ArrayList list = new ArrayList();
list.add("abc");
list.add("def");
list.remove(1); ---> 这行代码的返回值是字符串“def”
list.remove(o) : 移除集合list中的o对象,返回的是一个boolean类型,true代表移除成功,false代表移除失败
ArrayList list = new ArrayList();
list.add(9);
list.add(19);
list.add(3);
list.add(99);
list.remove(3);----> 移除的是数字3元素还是第3个元素? 移除的是第3个元素。
如果是需要移除元素3,则使用list.remove(Integer(3))
list.set(index,o) : 将集合中的第idnex个元素修改为o对象。
list.toArray() : 将这个集合list转成Object类型的数组。
LinkedList
list的链表实现。存放的数据在内存中不是连续的。以链表的形式保存,所以它的插入和删除比较快,不用改变其他元素的位置。null可以当做元素添加。同时LinkedList也不是线程安全的。
构造方法:
new LinkedList() ---> 创建一个空的list容器。(不需要指定容量)
普通方法:
list.size() 长度
添加:
list.add(o) 添加对象o到集合的末尾
list.add(index,o) 添加对象o到集合的第index位置。
list.addFirst(o) : 添加对象o到集合第一个位置 等同于list.add(0,o)
list.addLast(o) : 添加对象o到集合的最后一个位置 等同于add(o)
list.push(o): 将对象o添加到第一个位置 : 等同于 list.add(0,o)
查找:
list.get(index) : 获取集合的第index位置的元素
list.getFirst()
list.getLast();
list.element(): 获取第一个元素(不移除) list.get(0) 或者list.getFirst()
list.peek() 获取第一个元素(不移除) list.get(0) 或者list.getFirst() 或者 list.element()
list.peekFrist() : 获取第一个元素(不移除 ) 如果集合的长度是0,没有异常,直接返回null
list.peekLast() : 获取最后一个元素
删除:
list.remove() : 获取并删除第一个元素
list.remove(index) : 删除指定位置index上面的元素,返回被删除的对象.如果集合没有元素,删除时会出异常
list.remove(o) : 删除集合中的对象o ,返回boolean
list.removeFirst() :获取并删除第一个元素
list.removeLast(): 获取并删除最后一个元素
list.poll () : 删除第一个元素,并返回 等同于: list.remove(0) 如果集合没有元素,删除时不会出异常
list.pollFirst():删除第一个元素,并返回
list.pollLast() :删除最有一个元素,并返回
list.pop() : 获取并删除第一个元素, list.remove(0)
修改:
list.set(index ,o) : 将集合中的第index位置上的元素修改为o
Vector
Vector 也ArrayList 类似,都是继承abstractList,都实现了List接口。 Vector与ArrayList 最大的区别是 Vector是线程安全的,ArrayList是非线程安全的。Vector的效率低。
构造方法和普通方法与ArrayList一样。
如果需要保证数据的线程安全就使用Vector,其他一般的情况都使用ArrayList
Set
一个无序的Collection,且里面元素没有重复。这个重复是指元素之间的equals方法都是返回false。
set是一个集合,常用的set有: HashSet TreeSet
HashSet
实现了Set接口,继承了AbstractSet抽象类。基于哈希码的Set集合。Set是无序的,即放入的顺序与获取的顺序不一样,而且里面放入的元素的顺序不是恒久不变的。 HashSet不是线程安全的,即它的方法不是同步的。很多线程可以同时去修改一个HashSet。 如果是在多线程里面使用HashSet就需要自己来控制同步。
构造方法:
new HashSet(); ----> 创建一个空元素的Set容器。初始容量是16,加载因子是0.75
new HashSet(int n); ----> 创建一个初始容量为n的Set容器
普通方法:
set.size() : 返回容器里面放入元素的个数
set.add(o) : 将对象o放入集合set中,返回一个boolean类型,表示添加成功或失败,放入o已经存在集合里面 就添加失败,这个o与set里面每个元素都equals比较,都返回false,表示不在里面。
set.clear() : 清除set中的所有元素,长度为0
set.contains(o) : 判断对象o是否在集合set中,o对象与集合中的每个元素都 hashcode不一样,且equals也为 false,则表示o不在里面
set.remove(o) : 移除集合set中的o对象。返回boolean表示成功或者失败。 set中的remove没有通过下标移除 的方法,因为set没有顺序、没有下标
set.iterator(); : 将set转成一个迭代器,返回的是一个迭代器对象。
迭代器Iterator
从set中取值,不能使用普通的for循环去取每一个值,因为set没有下标。但可以将set集合转一个迭代器。
Iterator it = set.iterator();
it就是一个迭代器。
Iterator里面只有3个方法:
next() : 取出迭代器里面的下一个元素 (如果下一个元素没有了,报异常)
hasNext(): 判断是否有下一个元素 (如果返回真 可以继续使用next取元素)
remove() : 移除当前迭代器里面的元素
如果又一个set集合,要取出它的所有元素
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Iterator迭代器正在迭代一个集合的过程中,不能去集合里面添加或者删除数据;只能迭代完后再添加或者删除。
或者迭代的过程中使用迭代器的删除功能。
TreeSet
TreeSet也是线程不安全的集合。它里面不能放入null作为元素。
TreeSet: 一种有顺序的Set集合,不是元素添加的顺序,是按照元素的自然顺序排序。
TreeSet里面放入的元素必须能排序。即TreeSet里面所有的元素之间可以比较大小。
TreeSet里面放入的元素最终使用通过comparTo方法比较大小。即如果对象具有comparTo方法就可以放入这个集合里面,比如String、Integer、Double
如果一个对象能放入TreeSet里面,则在设计类的时候需要实现Comparable接口,实现里面comparTo方法,TreeSet才可以比较对象的大小,然后排序。
Map
Map也是一个集合,但它里面放入的元素需要成对保存。Map也称为键值对。即它的一个元素有两个对象一个是键一个是值。Map中的键kay是不能重复,但它的值value可以重复。
HashMap
HashMap是Map常用的实现类。即如果程序中需要一个Map,则可以去创建HashMap来使用。Map里面添加的数据是成对的出现,HashMap中可以将null作为键和值一起保存。同时HashMap不是线程安全的,效率比较高。HashMap放入的元素没有顺序。
常用的构造方法:
new HashMap() 创建一个初始容量16,加载因子0.75的空map集合。
功能方法:
map.put(k,v) ----> 将对象k和v作为一个元素放入map中。方法的返回值是:如果这个k是第一次放入,则返回 null,如果这个k以前放过,则这个函数返回的k对应的之前的v。
map中的k不能重复,如果放入值的时候,k已经存在map中,则后面v会覆盖前面的v。
map.size() ----> 获取map的长度,即map中元素的个数
map.containsKey(k) --> 判断这个map中是否有指定键k
map.containsValue(v)-->判断这个map中是否有指定的值v
map.get(k) ---> 通过键k或者对应的值v,如果没有这个键k则返回null。
map.isEmpty()---> 判断这个map是否没有元素
map.keySet() --> 取出map里面所有的键k,组成一个set容器。
map.remove(k) --> 通过一个键k移除map中的一个元素。如果这个键k存在,则返回是这个键对应的值,如果没 有这个键k,则返回null。
map中的键和值可以是任何类型,但一般是将整数或者字符串作为键。值可以是任何数据。
Hashtable
早期的Map的实现。它是线程安全的,所以效率低。 Hashtable不能放入null作为键和值,会报空指针异常。
Stack(栈)
继承了Vector,是Vector的子类,也属于List。 用来保存数据的 堆栈。特征是FILO:First In Last Out 即先进后出。将数据放入Stack里面 先放入的数据最后取出。(LIFO)
构造方法:
new Stack() : 创建一个空的堆栈。
普通方法:
peek() --> 获取这个集合中顶部的数据,但不移除
pop() ----> 获取集合顶部的数据,并移除
push(o) ----> 将对象o放入集合的顶部
Collections
如果在定义一个集合的时候就知道这个集合里面放入的具体的数据,可以不用创建一个集合再一个一个的add数据,可以使用Arrays的静态方法asList。
List list = Arrays.asList( 具体的数据 );
Collection是一个接口,Collections是一个类。Collections是用来操作集合的工具类型,类似于Arrays是操作数组的工具类一样,方法都是静态的,直接Collections.方法名 使用。
常用的方法:
Collections.addAll(c, o...) 将后面的数据o(可以有多个) 全部添加到c集合里面
Collections.binarySearch(c,o) : 使用二分查找,去集合c里面判断是否有对象o 。局限在 集合c中的元素能排 序才可以使用二分查找。(集合中的元素能比较大小,即定义类的时候实习了 Comparable接口)
Collections.copy(c1,c2) : 将c2集合中的数据,一个一个的放入c1集合里面,从c1的第一个位置开始,覆盖c1里 面的值。
Collections.fill(c,o) : 使用o数据来填充c集合的每个位置。即将集合c的每个位置上的数据修改为o。
Collections.max(c) : 查询c集合中的最大值。 c集合中必须放入可以比较的元素
Collections.replaceAll( c, x,y ) : 将集合c中的所有x值 使用y来替换。
Collections.reverse(c) :将集合c中的元素顺序反转
Collections.sort(c) : 将集合c中的元素从小到大排序
Collection 与Collections有什么区别?
Properties
Properties是一个工具类,它继承了Hashtable,Hashtable是一个Map,所以Properties也是一个Map集合。
它的作用一般是使用Properties对象去获取一个Properties文件中的数据。Properties文件一般是放配置文件。
Properties p = new Properties();//创建工具类对象
p.load(new FileInputStream("a.properties"));//使用对象去加载配置文件
p.get("addr"); //在对象里面 通过键 去获取值
泛型
集合相对于数组来说,有两个优点: 1、长度没有限制,可以不停的扩充。 2、放入的元素的类型没有限制,即一个集合里面什么类型的数据都可以放进去。
因为集合里面什么类型的数据都可以放入,则在从这个集合中取数据时候,无法知道原始类型,即使知道它的原始类型,在取出数据后还需要强转回去。 一般一个集合或者容器里面放入数据都相同的类型。
有了泛型后就可以约束集合里面只能放入指定的类型数据,好处是取数据的时候不再需要强转了,直接就是泛型定义的类型。
集合里面使用泛型:
语法是定义集合的时候 使用尖括号包含类型, 这个类型只能是复合类型,如果是需要放基本类型的数据,就是基本类型的包装类。
list里面: 例如: 定义一个集合,它里面只能放入字符串:
List();
Set里面,定义一个Set容器,它里面只能放入Student对象
Set ();
Map里面, 定义一个map容器,它里面的键是整数,值是字符串
Map <Integer,String> map = new HashMap <Integer,String> ();
foreach
for循环的另一种语法。
for循环基本语法是for( ; ; ){}
for循环的另一种语法: for( : ){ }
foreach的作用就是去容器里面取数据,所以foreach只用在去数组或者集合里面取数据,其他地方不会使用。
语法:
for( 类型 变量名 : 容器名 ){
//循环体,可以使用变量
}
容器名就是foreach去哪取数据。
foreach只能取数据,不能往容器中放数据。
图形界面
gui swing
JFrame: JFrame的布局是边界布局,JFrame将自己分成 东南西北中,5部分。向JFrame里面放入组件的时候默认都是放在中间,如果JFrame的四周没有组件,则中间的组件就拉伸到整个Frame。可以在放入组件的时候指定位置
JFrame jf = new JFrame();
jf.setBounds(500, 100, 500, 500);
jf.setDefaultCloseOperation(3);
JButton jb = new JButton("点击");
jf.add(jb);
JButton jb2 = new JButton("点击2");
jf.add(jb2,BorderLayout.NORTH );
JButton jb3 = new JButton("点击3");
jf.add(jb3,BorderLayout.EAST );
jf.setVisible(true);
JFrame中最多只能放5个组件。一般没有将组件直接放在JFrame,而是放在JPanel里面 再将JPanel放入JFrame里面。
可以去掉一个容器的布局。
如果JFrame没有布局,则在向Frame里面放入组件的时候,这个组件需要指定大小和位置。
JPanel,是java图形界面中的面板。,一般将组将放入其中,再将Panel放入Frame。 JPanel的布局默认是flowLayout,往它里面放入组件时,默认放在第一行中间,如果第一行显示不下,在到第二行中间。。。
如果需要将组件排列很整齐,可以设置容器的布局是GridLayout,网格布局。
jp.setLayout( new GridLayout( 5,5 )) ---> 设置jp的布局是一个5行5列
jp.setLayout( new GridLayout( 5,5,1,1 )) ---> 设置jp的布局是一个5行5列,行和列的间距是1个像素
JFrame不能设置背景颜色,其他的组件或者容器都可以设置背景颜色。
JPanel是一个面板,它里面有一个paint方法,paint是一个画图的方法,方法带一个形参Graphic 画笔,但默认的方法里面没有画东西。如果自己的图像界面需要去Jpane里面画东西,就需要重写这个方法,如果想重写就需要去继承java提供的JPanel类,然后再重写paint方法。
Graphic 画笔可以画 : 椭圆、矩形、直线、弧线、图片、字符串
例如: 画直线 g.drawLine(x,y,x2,y2)
画椭圆: g.drawOval(x,y,w,h)
画矩形: g.drawRec(x,y,w,h)
如果是画实心的就将draw改为fill
组件
常见组件:
JButton JTextField JLable JPasswordField
单例模式
单例模式是项目程序在运行的过程中某个类只能实例化一个对象,整个程序运行的时候使用的对象都是同一个。
设计单例模式的过程:
1、构造方法私有化
2、对外提供一个静态的方法,这个静态方法里面就可以调用自己的构造方法了
3、静态的属性,属性就是当前类的类型,静态方法将这个属性赋值
4、外部如果需要对象,就找这个类的静态方法,静态方法提供对象。静态方法将这个静态属性对象返回
单例模式有两种实现方式:
懒汉模式
懒汉模式是说类很懒,当整个类加载的时候,如果没有调用静态方法,则静态的属性先不实例化,如果确定你需要使用的时候再实例化。
public class People {
private static People p;
private People(){
}
public static People getInstance(){
if(p == null){
p = new People();
}
return p;
}
}
饿汉模式
在类加载的时候就将这个静态属性初始化了,即已经准备好了对象。
public class People {
private static People p = new People();
private People(){
System.out.println("实例化了People对象");
}
public static People getInstance(){
return p;
}
}
内部类
内部类: 即一个类A的定义在另一个类B的里面,则类A称为类B的内部类。
类的里面可以定义类,但方法里面的里面不能再定义方法。
如果一个类A要去使用另一个类B的属性或者方法,则就可以将类A的定义放在类B的里面,让A是B的内部类。这时内部类就可以直接使用外部类的属性和方法了。
内部类的分类:
1、成员内部类
class A{
private int x = 1;
public void a(){
int x = 2;
System.out.println("aaaa");
}
访问修饰符 class B{
private int x = 3;
public void a(){
int x = 4;
System.out.println(x);
}
}
}
//类B是类A的成员内部类
//如果是A里面需要使用B对象:
//则A里面可以直接:
B b = new B();
//如果其他地方需要创建B对象,还必须将创建A对象
//语法:
A a = new A();
A.B b = a.new B();
//或者:
A.B b2 = new A().new B();
将一个类的定义当做这个类里面的一个属性来定义。 这种成员内部类,如果需要在其他地方创建内部类,则还必须将创建外部类。
class C{
int x = 5;
}
class D{
//int x = 6;
}
class A extends C{
//private int x = 1;
public void a(){
int x = 2;
System.out.println("aaaa");
}
class B extends D{
//private int x = 3;
public void a(){
//int x = 4;
System.out.println(x);
}
}
}
//一个方法里面在使用一个变量的时候,先去这个方法里面寻找是否定义了方法的局部变量,如果方法里面没有定义再去当前类里面寻找是否定义了属性,如果当前类中没有定义这个属性,再去当前类的父类里面寻找,如果当前类的父类中没有,再去当前类的外部类中寻找属性,如果外部类没有再去外部类的父类中寻找。
2、静态内部类
在成员内部类的前面加static关键字,就变成了静态内部类。
class A{
static class B{
}
}
//静态内部类在创建的时候不需要创建外部类
A.B b = new A.B();
这种静态的内部类不能使用外部类非静态的属性和方法。
静态内部类很少使用。
3、方法局部内部类
将一个类的定义放在另一个类的方法里面。
class A{
public void method(){
class B{
public void method2(){
}
}
}
}
方法里面定义的局部内部类,只能给这个方法使用。方法里面定义的类也可以使用外部类的属性和方法。
4、匿名内部类
匿名是没有名字,即定义一个类,而类没有名字。
匿名内部类一般定义的时候就实例化使用,而且只能实例化一次。