存储批量性数据尽量使用集合,能使用集合就使用集合,能不使用数组就不使用数组,因为集合效率更高
- 一、掌握封装类的应用
对于简单类型数据,Java对它们进行了封装,使它们都有相应的封装类
简单数据类型 | 封装类 |
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
【为什么会出现封装类? 】
封装类是为了解决简单类型无法解决的问题,例如:将字符串“123”转换成整数类型后,再参与减法运算。
如果我们只使用简单数据类型来完成上面要求的功能,我们是根本没有办法做到的。这时就出现了封装类,我们可以通过相应的封装类提供的方法就能解决上面的问题。
例如:我们要将字符串“123”转换成int类型,我们就需要找到int类型对应的封装类:Integer,通过封装类Integer提供的parseInt()方法我们就可以把这个字符串”123”转换成int类型了,如下所示:
int num = Integer.parseInt(“123”);
所以封装类就是帮助我们完成简单数据类型完成不了的功能,即:简单数据类型完成不了的功能,我们通过相应的封装类来完成,例如:类型的转换工作,如:把一个字符串类型的文本数据转换成整型。
封装类类型的数据是以对象的形式存在的。
【自动装箱】
自JDK 1.5版本开始,Java语言提供了一种更为实用的功能——自动装箱技术。
Integer a = 10;
Integer b = 10;
System.out.println(a==b); //true
知识点:共享池
- 二、掌握集合框架包含的内容
【Java集合框架】
Collections:提供了对集合进行排序、 遍历等多种算法实现
Java集合框架为我们提供了一套性能优良、使用方便的接口和类,它们位于java.util包中
【Collection】
Collection 接口存储一组不唯一,无序的对象
List 接口存储一组不唯一,有序(插入顺序)的对象,即有序可重复
Set 接口存储一组唯一,无序的对象,即无序不重复
Map接口存储一组键值对象,提供key到value的映射(无序)
注:集合中存储的都是对象,而不是简单数据类型。
- 三、掌握ArrayList和LinkedList的使用
- ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高
- LinkedList采用链表存储方式。插入、删除元素时效率比较高
集合可以存储不同类型的对象,但建议存储相同类型的对象,将来遍历方便转型,比较灵活
当我们没有使用泛型的时候,遍历集合必须自己实现强制类型转换
【List】
dogs.add(2, feifeiDog); // 添加feifeiDog到指定位置
自JDK1.5版本以后,Java提供了一种增强型的for循环语句来进一步方便集合元素的遍历:
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
List al = new ArrayList();
al.add(s1);
al.add(s2);
al.add(s3);
for (Object o : al) {
Student s = (Student)o;
s.study();
}
List接口提供相应方法remove()、contains(),直接使用即可
List接口常用方法
方法名 | 说 明 |
boolean add(Object o) | 在列表的末尾顺序添加元素,起始索引位置从0开始 |
void add(int index,Object o) | 在指定的索引位置添加元素。索引位置必须介于0和列表中元素个数之间 |
int size() | 返回列表中的元素个数 |
Object get(int index) | 返回指定索引位置处的元素。取出的元素是Object类型,使用前需要进行强制类型转换 |
boolean contains(Object o) | 判断列表中是否存在指定元素 |
boolean remove(Object o) | 从列表中删除元素 |
Object remove(int index) | 从列表中删除指定位置元素,起始索引位置从0开始 |
【ArrayList】
import java.util.ArrayList;
import java.util.List;
public class ArrayList_Demo {
//示例:用于演示方法的返回类型为List,一般当一个方法返回的对象为ArrayList时,方法的返回类型一般写为List,这样程序的扩展性更好
public List getList(){
List al = new ArrayList();
al.add(new Dog());
al.add(new Dog());
return al;
}
public static void main(String[] args) {
//示例一:List集合中可以加入不同类型的对象,但是一般不这么使用,因为灵活性太差,一般在使用List时,该集合中加入的都是相同类型的对象,但是需要知道List集合中是可以加入不同类型的对象
List list1 = new ArrayList();
String username = "Lucy";
Student stu = new Student();
Dog dog = new Dog();
list1.add(username);
list1.add(stu);
list1.add(dog);
System.out.println(list1);
//示例2:List集合中也可以放相同类型的对象,一般最为常用
List list2 = new ArrayList();
list2.add("lucy");
list2.add("lili");
list2.add("Haimeimei");
list2.add("lilei");
System.out.println(list2);
}
}
【LinkedList】
插入、删除操作频繁时,可使用LinkedList来提高效率
LinkedList还额外提供对头部和尾部元素进行添加和删除操作的方法
LinkedList 实现栈和队列
- 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
- 队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表
import java.util.LinkedList;
public class LinkedList_Demo {
public static void main(String[] args) {
LinkedList_Demo ld = new LinkedList_Demo();
//通过LinkedList实现队列
LinkedList queue = new LinkedList();
queue.addFirst("A");
queue.addFirst("B");
queue.addFirst("C");
queue.addFirst("D");
for(int i = 0; i<queue.size();){
System.out.print(queue.removeLast() + " ");
}
System.out.println();
System.out.println(queue.size());
System.out.println("====================");
//通过LinkedList实现栈
LinkedList stack = new LinkedList();
stack.addFirst("A");
stack.addFirst("B");
stack.addFirst("C");
stack.addFirst("D");
for(int i = 0; i<stack.size();){
System.out.print(stack.removeFirst() + " ");
}
}
}
LinkedList的特殊方法
方法名 | 说 明 |
void addFirst(Object o) | 在列表的首部添加元素 |
void addLast(Object o) | 在列表的末尾添加元素 |
Object getFirst() | 返回列表中的第一个元素 |
Object getLast() | 返回列表中的最后一个元素 |
Object removeFirst() | 删除并返回列表中的第一个元素 |
Object removeLast() | 删除并返回列表中的最后一个元素 |
【Set】
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSet_Demo {
public static void main(String[] args) {
Set set = new HashSet();
set.add("one");
set.add("one");
set.add("two");
//Set集合中不会加入重复的对象,Set集合在加入对象时,判断的是对象的内容是否一样,而不是对象的地址
// set.add(new String("one"));
System.out.println(set);
//HashSet的size()方法用于返回该HashSet集合对象的长度
System.out.println("set的长度为:" + set.size());
//Set集合只能使用迭代器(Iterator)来进行遍历
Iterator iter = set.iterator();
while(iter.hasNext()){
String s = (String)iter.next();
System.out.println(s);
}
//扩展练习
HashSet hs = new HashSet();
hs.add(5);
hs.add(new Integer(5));
hs.add(new Integer("5"));
hs.add(new Integer('5'));
//思考:此时hs这个HashSet集合对象中有多少个对象?
// System.out.println(hs);
// System.out.println(hs.size());
}
}
Set里的元素是无序不重复的;
如何保证set里的元素不重复:放到容器里的对象用equals()判断
为了提高比较效率而采用Hash表的原理
- 覆盖hashCode()方法;
- 添加元素时先调用hashCode() (Set再往里加入元素时,会自动调用被加入对象的hashCode方法)
- 利用hashCode()返回的值定位到放置位置;
- 如该处存在对象,再调用equals(),如果相等就不往集合中加入了
- 好处:减少了比较次数
eqauls方法和hashCode方法的规定:
- 如果两个对象相同,那么它们的hashCode值一定要相同
- 如果两个对象的hashCode相同,它们并不一定相同
hashCode码相同,内容不一定相同;(就相当于字典同一页上存储了不同的汉字)
hashCode码类似于字典的页码,一页字典上可以放很多字,hashCode码相当于一片内存区域(hashCode码和字典的页码相似),一片内存区域可以存很多对象
Set集合中添加对象的方式:当向Set集合中添加一个对象(给这个对象起个名字叫:A)时,首先会调用这个A对象的hashCode方法,A对象的hashCode方法返回一个值(这个值就代表内存的一片区域,我们就可以把这片区域看成是我们选中的字典中的某一页),这时Set集合会查看这片区域(字典中的这一页)上是否有要加入的这个A对象,如果没有则Set集合直接把这个A对象加入到Set集合中,如果发现这片区域中有一个和A对象看上去相似的对象,这时再调用被加入对象(就是A对象)的equals方法和这个已经有的对象比较一下看看是不是同一个对象,如果是则不再把A对象加入到Set集合中,如果不是,则把A对象再加入到Set集合中。
- 四、掌握HashMap的使用
Map是一个接口,它也是一种集合,它与List接口不同,Map的结构是采用“键-值”对的形式存放对象的。
Map接口的常用方法:
- public int size():返回Map集合同元素的个数。
- public boolean isEmpty():如果Map集合为空,则返回true,否则返回false。
- public Object get(Object key):返回key(键值)对应的对象。
- public Object put(Object key, Object value):向Map中建立key和value对,第1个参数为键值,第2个参数为该键对应的值,两个参数都是Object类型。如果key(键值)在Map中已经存在,则将该key对应的值,替换成value。并返回原有的值。如果key和value不存在,则put方法返回null。(要求key值不能为空,value可以为空)
- public Object remove(Object key):从Map中移除指定key对应的key-value对。如果key存在,在移除的同时,并返回该key对应的value
- public void clear():清空整个Map。
- public Set keySet():返回一个Set类型的集合对象,其中Set集合中存储的是该Map中所有的key值。(Map集合的遍历要通过Set集合的遍历间接实现)
HashMap是Map接口的一个具体实现类,一般我们都使用它。
【Map接口常用方法】
方法名 | 说 明 |
Object put(Object key, Object val) | 以“键-值对”的方式进行存储 |
Object get (Object key) | 根据键返回相关联的值,如果不存在指定的键,返回null |
Object remove (Object key) | 删除由指定的键映射的“键-值对” |
int size() | 返回元素个数 |
Set keySet () | 返回键的集合 |
Collection values () | 返回值的集合 |
boolean containsKey (Object key) | 如果存在由指定的键映射的“键-值对”,返回true |
【Vector和ArrayList的异同 】
实现原理相同,功能相同,很多情况下可以互用
两者的主要区别如下
- Vector线程安全,ArrayList重速度轻安全,线程非安全
- 长度需增长时,Vector默认增长一倍,ArrayList增长50%
【Hashtable和HashMap的异同】
实现原理相同,功能相同,在很多情况下可以互用
两者的主要区别如下
- Hashtable继承Dictionary类,HashMap实现Map接口
- Hashtable线程安全,HashMap线程非安全
- Hashtable不允许null值,HashMap允许null值
开发过程中,最好使用ArrayList和HashMap
- 五、掌握Iterator的使用
【如何遍历List集合呢?】
方法1:通过for循环和get()方法配合实现遍历
方法2:通过迭代器Iterator实现遍历
- 所有集合接口和类都没有提供相应遍历方法,而是由Iterator实现集合遍历
- Collection 接口的iterate()方法返回一个Iterator接口类型的对象,然后通过Iterator接口的两个方法可实现遍历
- boolean hasNext(): 判断是否存在另一个可访问的元素
- Object next(): 返回要访问的下一个元素
Iterator it = dogs.iterator();
while (it.hasNext()) {
Dog dog = (Dog) it.next();
System.out.println(dog.getName()+"\t"+dog.getStrain());
}
迭代器内不存储数据,只存在映射
List和Set才有迭代器,Map没有
标准for语句不能遍历Set集合,因为Set没有下标,但增强型for语句可以遍历Set集合
当使用Iterator遍历集合对象时,此时我们不能向所遍历的集合对象里动态添加或删除该集合中的对象,否则会抛出如下异常: java.util.ConcurrentModificationException
★ 正确示例代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class HelloWorld {
public static void main(String[] args) {
int i = 1;
List list = new ArrayList();
list.add("one");
list.add("two");
list.add("three");
Iterator iter = list.iterator();
while(iter.hasNext()){
String str = (String)iter.next();
System.out.println(str);
//在使用Iterator遍集合对象list时,还动态向list集合中添加对象
//正确的做法是,使用Iterator将集合遍历完毕后再向list集合中添加其它对象,不能同时使用Iterator遍历集合和向被遍历的集合中添加或删除对象!
}
//此时向list集合中添加对象时,不会抛出异常,因为已经使用Iterator遍历完list集合了
list.add("s" + i);
}
}
- 六、掌握泛型集合的使用
泛型的作用:1、约束集合中存储的对象类型 2、简化迭代遍历(无需类型强制转换)
List<Book> al = new ArrayList<Book>()
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class FX_Demo_1 {
public static void main(String[] args) {
//由于使用了泛型,所以此时list集中合只能存储String类型的对象,不能再向这个集合中放入其它类型的对象
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
// list.add(new Integer(1));
// for(int i= 0 ; i<list.size(); i++){
// System.out.println(list.get(i));
// }
//由于使用了泛型,所以此时iter迭代器,迭代出来的对象都是String类型的对象,这时就不用再进行强制类型转换了
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
String s = iter.next();
System.out.println(s);
}
}
}
Book b1 = new Book();
Book b2 = new Book();
Book b3 = new Book();
List<Book> l = new ArrayList<Book>();
l.add(b1);
/*
* 由于在创建集合对象时,使用了泛型,明确规定了将来这个集合对象中只能放Book类型的对象
* 所以不能再向这个集合中放入其它类型的对象了
*/
// l.add("1a");