1.集合类
1.1为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一 种方式。
1.2数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
1.3集合类的特点
1.用于存储对象的容器。
2.集合的长度是可变的。
3.集合中不可以存储基本数据类型值。
2.集合框架
集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。
3.框架的顶层Collection接口
Collection的常见方法:
1.添加
boolean add(Object obj):
boolean addAll(Collection coll):
2.删除
boolean remove(object obj):
boolean removeAll(Collection coll);
void clear();
3.判断
boolean contains(object obj):
boolean containsAll(Colllection coll);
boolean isEmpty():判断集合中是否有元素。
4.获取:
int size():
Iterator iterator():取出元素的方式:迭代器。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
迭代是取出集合中元素的一种方式。
因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。
5.其他:
boolean retainAll(Collection coll);取交集。
Object[] toArray():将集合转成数组。
4.Collection的两大子接口
|-- List(列表):有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|-- Set(集):元素不能重复,无序。
4.1 Collection--->>List
List:特有的常见方法:有一个共性特点就是都可以操作角标。
1.添加
void add(index,element);
void add(index,collection);
2.删除;
Object remove(index):
3.修改:
Object set(index,element);
4.获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);
>>List集合包含:list集合是可以完成对元素的增删改查。
4.1.1 Vector:内部是数组数据结构,是同步的。增删,查询都很慢。
vector 特有的方法:
1.添加
addElement(Object);
2.获取
Enumeration();
|--addElement(Object);
|--nextElement();
public class VectorDemo { public static void main(String[] args) { Vector v = new Vector(); v.addElement("abc1"); v.addElement("abc2"); v.addElement("abc3"); v.addElement("abc4"); Enumeration en = v.elements();//vector特有的方法 while(en.hasMoreElements()){ System.out.println("nextelment:"+en.nextElement()); } Iterator it = v.iterator();//共有迭代器 while(it.hasNext()){ System.out.println("next:"+it.next()); } } }
4.1.2.LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。
LinkedList一些常用方法:
1.添加
在此列表的开头插入指定的元素。
2.修改void addFirsrt(Object)
Boolean offerFirst(Object)
在此列表的结尾插入指定的元素。
void addLast(Object)
Boolean offerLast(Object)
3.获取将此列表中指定位置的元素替换为指定的元素。
Object set(int index,Object obj)
4.删除获取但不移除此列表的第一个元素
Object getFirst():如果此列表为空,则抛异常。
Object peakFirst():如果此列表为空,则返回 null。
获取但不移除此列表的最后一个元素
Object getLast():如果此列表为空,则抛异常。
Object peakLast():如果此列表为空,则返回 null。
获取并移除此列表的第一个元素;
Object removeFirst():如果此列表为空,则抛异常。
Object pollFirst():如果此列表为空,则返回 null。
获取并移除此列表的最后一个元素;
Object removeLast():如果此列表为空,则抛异常。
Object pollLast():如果此列表为空,则返回 null。
/* * 请使用一个LinkedList来模拟一个堆栈或者队列数据结构 * 堆栈:先进后出 * 队列:先进先出 * 创建一个容器 */ class DuiLie { private LinkedList list; DuiLie() { list = new LinkedList(); } void myAdd(Object obj) { list.addLast(obj); } public Object myGet() { return list.removeFirst(); } public Boolean isNull() { return list.isEmpty(); } } public class LinkedListTest { public static void main(String[] args) { DuiLie dl = new DuiLie(); dl.myAdd("abc1"); dl.myAdd("abc2"); dl.myAdd("abc3"); while (!dl.isNull()) { System.out.println(dl.myGet()); } } }
4.1.3 ArrayList:内部是数组数据结构,是不同步的。查询很快。
ArrayList()构造一个初始默然容量为 10 的空列表。
/* * 去除ArrayList中重复元素 * */ public class ArrayListTest { public static void main(String[] args) { // TODO Auto-generated method stub //创建一个ArrayList容器 ArrayList al=new ArrayList(); al.add("abc1"); al.add("abc2"); al.add("abc1"); al.add("abc1"); al.add("abc3"); System.out.println(al); al=getSingleElements(al); System.out.println(al); } public static ArrayList getSingleElements(ArrayList al) { // TODO Auto-generated method stub //新建一个ArrayList容器装 ArrayList temp=new ArrayList(); //获取迭代器 Iterator it=al.iterator(); while(it.hasNext()){ Object obj=it.next(); if(!temp.contains(obj)) temp.add(obj); } return temp; } }
4.2 Collection--->>set
set:集合中元素不可以重复。
set集合包含:
4.2.1 hashdSet:内部数据结构是哈希表,线程不安全,存取速度快。
HashSet:通过equals方法和hashCode 方法来保证元素的唯一性。
注:如果元素要存储到HashSet中,必须覆盖HashCode和equals方法。
public class HashSetDemo2 { public static void main(String[] args) { HashSet hs = new LinkedHashSet(); hs.add(new Person("abc1", 21)); hs.add(new Person("abc2", 22)); hs.add(new Person("abc2", 23)); hs.add(new Person("abc2", 24)); hs.add(new Person("abc2", 22));// 会出现两个abc2 Iterator it = hs.iterator(); while (it.hasNext()) { Person p = (Person) it.next(); System.out.println("name:" + p.getName() + ".." + "age:" + p.getAge()); } } }
4.2.2TreeSet:线程不安全,可以对Set集合中的元素进行排序。
TreeSet:通过compareTo或者compare 方法中的来保证元素的唯一性。元素是以二叉树的形式存 放的。
TreeSet排序1:
让元素具备排序功能,元素就必须实现Comparable接口,覆盖compareTo方法。
TreeSet排序2:
用比较器的方法让集合自身具备比较功能,先定义一个类实现Comparator接口,覆盖compare方法,将该类对象作为参数传递给TreeeSet的构造函数。
/* *对字符串按长度排序 * */ public class TreeSetTest { public static void main(String[] args) { // TODO Auto-generated method stub TreeSet ts = new TreeSet(new ComparatorByLength()); ts.add("aaaa"); ts.add("gdaa"); ts.add("gd"); ts.add("hjt"); ts.add("zss"); Iterator it = ts.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } class ComparatorByLength implements Comparator{ @Override public int compare(Object o1, Object o2) { // TODO Auto-generated method stub String st1=(String)o1; String st2=(String)o2; int temp=st1.length()-(st2.length()); return temp==0?st1.compareTo(st2):temp; } }
4.3 Map
Map:一次添加一对元素,也叫双集合。其实Map集合中存储的是键值对。Map集合中必须保证键值的唯一性。
常用方法:
1.添加
value put(key,value):返回前一个和key关联的值,如果没有则返回null;
2.判断
boolean containsKey(key)boolean containsValue(value)boolean isEmpty();
3.获取
value get(key):通过键获取值,如果没有该键则返回null;当然可以通过是否返回null来判断是否包含指定键。
4.删除
void clear();清空集合value remove(key);根据指定的key删除键值对。
注:Map存相同的键值会覆盖。
public class MapDemo { public static void main(String[] args) { Map<Integer,String> map = new HashMap<Integer,String>(); map.put(8,"zhaoliu"); map.put(2,"zhaoliu"); map.put(7,"zhouqi"); map.put(6,"niuba"); method(map); method_2(map); } public static void method_2(Map<Integer,String> map){ //通过值集合取值 Collection<String> values = map.values(); Iterator<String> it2 = values.iterator(); while(it2.hasNext()){ System.out.println(it2.next()); } /* * 通过Map转成set就可以迭代。 * 找到了另一个方法。entrySet。 * 该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型 */ Set<Map.Entry<Integer, String>> entrySet = map.entrySet(); Iterator<Map.Entry<Integer, String>> it = entrySet.iterator(); while(it.hasNext()){ Map.Entry<Integer, String> me = it.next(); Integer key = me.getKey(); String value = me.getValue(); System.out.println(key+"..."+value); } } public static void method(Map<Integer,String> map){ //取出map中的所有元素。 //原理,通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键, //在对每一个键通过map集合的get方法获取其对应的值即可。 Set<Integer> keySet = map.keySet(); Iterator<Integer> it = keySet.iterator(); while(it.hasNext()){ Integer key = it.next(); String value = map.get(key); System.out.println(key+":"+value); } } }
4.4 Map常用的子类
Hashtable:内部结构是哈希表,是同步的,不允许null作为键作为值。
HashMap:内部结构是哈希表,是不同步,允许null作为键作为值。
TreeMap:内部结构是二叉树,是不同步,可以对Map集合的键进行排序。
Properties:用来存储键值对行的配置文件信息。
5.泛型(JDK1.5新特性)
5.1.1 泛型的特点
5.1.2 泛型的使用:
- 提高了程序的安全性
- 将运行期遇到的问题转移到了编译期
- 省去了类型强转的麻烦
- 泛型类的出现优化了程序设计
当操作的引用型数据类型不确定的时候就使用泛型<>,将要操作的引用数据类型传入即可,其实泛型<>就是一个用于接收具体引用数据类型的参数范围,在程序中只要用到带有<>的就要明确具体引用数据类型。
5.1.3 泛型的擦除:
泛型技术是给编译器使用的技术,在编译时使用确保了数据类型的安全,运行时会将泛型擦去,生成的class的文件中是不带泛型的,这个称为泛型的擦除(其实是为兼容以前的类加载器)。
5.1.4 泛型的补偿:
运行时通过获取元素的类型进行转换动作,不用使用者再强行转换。
注:当方法是静态的时候,不能访问类定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上。
5.1.5泛型的上限:
泛型的通配符:?
? extends E:接收E类型或者E的子类型对象。上限!
一般在存储元素时都是用上限,因为取出时都是按照上限类来运算的,不会出现安全隐患。
5.1.6泛型的下限:
? super E :接收E类型或者E的父类型。下限!
通常在对元素进行取出操作时使用下限。
public class MapDemo { public static void main(String[] args) { Map<Integer,String> map = new HashMap<Integer,String>();//<>泛型的使用 map.put(8,"zhaoliu"); map.put(2,"zhaoliu"); map.put(7,"zhouqi"); map.put(6,"niuba"); //通过值集合取值 Collection<String> values = map.values();//<>泛型的使用 Iterator<String> it2 = values.iterator();//<>泛型的使用 while(it2.hasNext()){ System.out.println(it2.next()); } } }
6.集合的使用技巧:
1.需要唯一性:Set
需要制定顺序:TreeSet
不需要制定顺序:HashSet
想要一个和存储一致的顺序(有序):LinkedHashSet
2.不需要唯一性:List
需要频繁增删:LinkedList
不需要频繁增删:ArrayList
7.集合框架工具类
7.1.1Collections:里面的方法都是静态的。
常用方法:
void sort(List<T> list);自然排序
int binarySearch(List<? extends Comparable<? super T>> list, T key):二分法查找
void reverseOrder(List<T> list):反转
void fill(List<? super T> list, T obj):全部替换
void shuffle(List<T> list):随机排列替换
7.1.2 Arrays:里面的方法都是静态的。
常用方法:
asList():将数组转成集合(以调用集合的方法)
注意:
1.如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
2.如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
3.数组的长度是固定的,所以对于集合的增删方法是不可以使用的否则会发生UnsupportedOperationException
7.1.3 Collection:
Object[ ]
toArray():将集合转成数组(可以对集合中的元素操作的方法进行限定。不允许对其进行增删。)<T>[ ] toArray(T[] a):将集合转成数组(可以对集合中的元素操作的方法进行限定。不允许对其进行增删。)
toArray方法需要传入一个指定类型的数组。
如何确认数组长度?
1.如果长度小于集合的size(),那么该方法就创建一个与集合相同size()的数组。
2.如果长度大于集合的size(),难么该方法就使用指定的数组存储集合的元素,其他位置默认为null。
8.增强for(JDK1.5新特性)
8.1 格式:
for(类型 变量 :Collection集合|数组){...}
8.2 传统for和高级for的区别?
1.传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
2.高级for是传统for一种简化形式。
3.它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。
4.对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
5.如果要对数组的角标进行操作建议使用传统for。
注:不可以直接使用高级for遍历map,但是如果可以将map转成单列的set,就可以用了。
public class ForeachDemo { public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>(); map.put(3, "zhagsan"); map.put(1, "wangyi"); map.put(7, "wagnwu"); map.put(4, "zhagsansan"); for (Integer key : map.keySet()) {// 高级for String value = map.get(key); System.out.println(key + "..." + value); } for (Map.Entry<Integer, String> me : map.entrySet()) {// 高级for Integer key = me.getKey(); String value = me.getValue(); System.out.println(key + ":" + value); } } }
9.可变参数函数(JDK1.5新特性)
函数的可变参数:
其实就是一个数组,但是接收的是数组的元素。自动将这些元素封装成数组。简化了调用者的书写。
注意:可变参数类型,必须定义在参数列表的结尾。
public class ParemterDemo { public static void main(String[] args) { int sum = newAdd(5,1,4,7,3); System.out.println("sum="+sum); int sum1 = newAdd(5,1,2,7,3,9,8,7,6); System.out.println("sum1="+sum1); } public static int newAdd(int a,int... arr){//可变参数类型 int sum = 0; for (int i = 0; i < arr.length; i++) { sum+=arr[i]; } return sum; } }
10.静态导入
静态导入:其实导入的是类静态中的静态成员。
import static java.util.Collections.*;//静态导入 import static java.lang.System.*;//静态导入 public class StaticImportDemo { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("abc3"); list.add("abc7"); list.add("abc1"); out.println(list);//可省掉类名System的书写 sort(list);//可省掉类名Collections的书写 System.out.println(list); String max = max(list); System.out.println("max="+max); } }
11.其他对象
11.1System:类中的方法和属性都是静态的。
常见的方法:
long currentTimeMillis();获取当前时间的毫秒值。
getProperties():获取系统信息
String getProperty(String key):获取指定系统信息
setProperties(Properties props):设置系统信息
String setProperty(String key, String value):设置指定键的系统信息
gc():运行垃圾回收器。
public class SystemDemo { //获取line.separator的系统信息并把它作为一个常量使用 private static final String LINE_SEPARATOR = System.getProperty("line.separator");//获取line.separator public static void main(String[] args) { long l = System.currentTimeMillis();//获取当前时间的毫秒值 System.out.println(l); System.out.println("hello-"+LINE_SEPARATOR+" world"); //给系统设置一些属性信息。这些信息是全局,其他程序都可以使用。 System.setProperty("myclasspath", "D:\\myclass"); demo_1(); } //获取系统信息并遍历 public static void demo_1(){ Properties prop = System.getProperties();//获取系统信息 Set<String> nameSet = prop.stringPropertyNames(); for(String name : nameSet){ String value = prop.getProperty(name); System.out.println(name+":"+value); } } }
11.2 Runtime
Runtime:没有构造方法摘要,说明该类不可以创建对象。
又发现还有非静态的方法。说明该类应该提供静态的返回该类对象的方法。
而且只有一个,说明Runtime类使用了单例设计模式。
常用的方法:
runtime getRuntime():返回与当前 Java 应用程序相关的运行时对象。
exec("指定程序路径或名称"):执行某个程序
public class RuntimeDemo { public static void main(String[] args) throws IOException, InterruptedException { Runtime rt = Runtime.getRuntime(); Process p = rt.exec("qq.exe");//执行某某程序 Thread.sleep(4000);//线程等待 p.destroy();//杀掉程序 } }
11.3 Math
Math:提供了操作数学运算的方法。都是静态的。
常用的方法:
abs():返回一个数的绝对值。
ceil():返回大于参数的最小整数。
floor():返回小于参数的最大整数。
round():返回四舍五入的整数。
pow(a,b):a的b次方。
random():0.0-1.0之间的随机数。
randomDouble():随机数
randomInt():随机数
public class MathDemo { public static void main(String[] args) { double d1 = Math.ceil(12.56);// 12.0 double d2 = Math.floor(12.56);// 13.0 double d3 = Math.round(12.46);// 12.0 System.out.println(d3); Random r = new Random(); for (int i = 0; i < 10; i++) { double d = Math.ceil(Math.random() * 10); System.out.println(d); } } }
11.4 Date
1.日期对象和字符串之间的转换
1.1.将日期格式的字符串-->日期对象。
使用的是DateFormat类中的parse()方法。
1.2.将日期对象-->日期格式的字符串。
使用的是DateFormat类中的format方法。
2.日期对象和毫秒值之间的转换。
2.1毫秒值-->日期对象 :
1.通过Date对象的构造方法 new Date(timeMillis);
2.还可以通过setTime设置。
因为可以通过Date对象的方法对该日期中的各个字段(年月日等)进行操作。
2.2 日期对象-->毫秒值:getTime方法。因为可以通过具体的数值进行运算。
public class DateDemo { public static void main(String[] args) throws ParseException { methodDemo_1(); methodDemo_2(); methodDemo_3(); } /*将日期格式的字符串-->日期对象。 *使用的是DateFormat类中的parse()方法。 */ public static void methodDemo_3() throws ParseException { String str_date = "2013---8---21"; DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG); dateFormat = new SimpleDateFormat("yyyy---MM---dd"); Date date = dateFormat.parse(str_date);//将日期格式的字符串-->日期对象。 System.out.println(date); long time = date.getTime();//日期对象的毫秒值 System.out.println(time); } public static void methodDemo_2() { Date date = new Date(); //获取日期格式对象。具体着默认的风格。 FULL LONG等可以指定风格。 DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG); dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG); //自定义风格 dateFormat = new SimpleDateFormat("yyyy:MM:dd"); String str_date = dateFormat.format(date); System.out.println(str_date); } public static void methodDemo_1() { long time = System.currentTimeMillis();//将日期转换成毫秒值 Date date = new Date();//将当前日期和时间封装成Date对象。 System.out.println(date); Date date2 = new Date(time);//将指定毫秒值封装成Date对象。 System.out.println(date2); } }