集合:
1、作用: 保存多条数据。
唠叨:同样是保存数据,其保存的内容不限,长度不限。
2、集合间的相互关系:
Collection--Set —HashSet
--List—ArrayList
—LinkedList
Map—HashMap
集合在底层实现时:依然使用数组,但是性能优于数组。
一、
1、List
1)list存储不唯一,有序的数据。
2)ArrayList本质上是长度可变的数组,遍历或者随机访问时效率更高。
LinkedList使用链式存储,插入或者删除时效率更高。
3)常用方法:
a) 添加add(Object obj)//顺序添加
Add(int index,Object obj)//在指定位置添加
b) 修改set(int index,Object obj)//修改指定下标的值
c) 删除remove(int index)//通过下标删除
Remove(Object obj)//删除指定数据
d) get(int index)//查看指定下标的值
e)获取及和大小:size()
4)如果集合中存储的数据是对象时,取出数据后,需要向下转型
List list =new ArrayList();
List.add(new Son());
Son s = (Son)list.get();//取出对象后,强转
2、LinkedList
1) 之前ArrayList拥有的方法,LinkedList同样拥有
2) LinkedList独有方法:
a). addFirst(Object obj);
b). addLast(Object obj);
c). removeFirst(Object obj);
d). removeLast(Object obj);
e). getFitst(Object obj);
f). getLast(Object obj);
注:如果调用上面方法,那么new对象时,声明使用LinkedList
示例:LinkedList list = new LinkedList();
主要是 实际工作中的差别,方法基本相同。
3、增强for循环
4、泛型
作用:限定集合或方法中添加的数据只能是限定的类型,以保证集合中数据的一致性
语法:<限定的数据类型>
示例:List<User> list = new ArrayList<User>();表明list中只能添加User类型的对象
注:添加泛型的集合,使用foreach遍历时,可以直接使用泛型中的类型接收数据
示例:for(User u:list){}
当时出了这样一个 bug:
public class ArrayList(){
public static void main(String[] args){
List myList = new ArrayList();
}
}
//然后就报错了,这是因为,他会循环调用自身,我们起的名字跟人家用的名字重名了,重名其实不要紧,最重要的是,这样就不认为ArrayList 是一个 List,需要让我们的ArrayList 实现List接口。好吧,最好的办法 还是把我们的名字改掉。
//我们的类不要叫做ArrayList。
相同的bug后面遇到的是,在 使用ssh框架的时候,在action里面不要使用,get或者 set来为方法命名。这样反射的时候,会带着不可调和的bug继续带着web程序 在服务器上跑。纠结再三,发现报了一个异常,他去掉了我的get,然后留了那个方法后面的字符。以及,在使用oracle的时候,开始少写了一个药品生产日期的字段。然后在修改表结构的时候,多加了一个字段叫做date。然后 同样悲剧了。其实 这些都是隐含的规定,慢慢慢慢才知道的,就跟我们在定义变量的时候 使用 class 或者 interface一样。是不应该这样做的。也是极力要避免的,事实上,如果不避免,编译器会提醒你的。如果编译器不能勾引起重视,那么在运行的时候一定会。
二、Set接口
存储特点:存储唯一无序的数据,即使数据重复添加,在数据显示的时候也不会重复。
常用实现类: HashSet
常用方法:
添加:add(Object o);
判断:isEmpty()
删除:remove()
包含:contains()//判断集合中是否包含该元素
遍历:两种方式:
Foreach
迭代 使用迭代器
Iterator it = 集合.iterator();
While(it.hasNext()){
It.next();//获取每一个数据,返回数据类型为:Object。
}
三、Map集合
a) 实现类HashMap
b) 存储特点:以键值对方式存储(key-value) key值不允许重复,value值可以重复
c) 常用方法:
i. 添加:put(key,value)
ii. 删除 remove(key)
iii. 查看 get(key)单个数据访问
iv. 获取key值集合
v. keySet()返回类型是 keySet
vi. 获取value值的集合 返回 Collection值类型
vii. 判断key值是否存在
viii. containskey(key)
(d) 添加泛型 Map<String,User> map = new HashMap<String,Map>();
限定key值为String类型,限定value为User类型
Java中的集合框架在添加数据时都会向上转型为Object类型,那么取出数据时需要强制类型转换,但是如果集合框架添加了泛型则取出数据时,不需强转。
练习:DVD的管理 和添加
晚一点儿 再弄 先打游戏。跟朋友一起
自己写例程的时候竟然还发现了 这个 addAll();方法。竟然不知道。现在 用一下吧。
剩下的代码分开写吧。因为这里面有一个 关于 ConcurrentModificationException 要说明一下。因为 确实 可能出现过bug。简要说明就是 遍历就是遍历,如果在遍历的时候被遍历的集合中的元素数量发生改变的话,那么遍历就不能正常进行,带来数量改变的就只有add 和 remove的操作,所以在遍历的过程中是不能够执行这两个方法的,合理的方法是,在遍历的过程中,对要增加和删除的操作标记好当前元素在集合中的位置【因为 list有序】,然后遍历完成之后,在找到对应元素增加或者删除。
【理解成有个傻孩子,在数糖果,你在他数的过程中,是不能往里面增加糖果,或者拿走糖果的,如果这样做,他就一定会数乱。数乱就一定会报ConcurrentModificationException】
参考如何在list中删除特定的元素:http://www.cnblogs.com/letben/p/5182947.html
示例代码:
package CollectionPart; public class EntityForArrayList { private int id; private String name; private int gender;//0男;1女 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getGender() { return gender; } public void setGender(int gender) { this.gender = gender; } @Override public String toString() { return "EntityForArrayList [id=" + id + ", name=" + name + ", gender=" + gender + "]"; } public EntityForArrayList(int id, String name, int gender) { this.id = id; this.name = name; this.gender = gender; } public EntityForArrayList() { super(); } }
package CollectionPart; import java.util.ArrayList; import java.util.List; public class ArrayList1 { public static void main(String[] args) { List myList = new ArrayList(); EntityForArrayList entity1 = new EntityForArrayList(1, "letben", 0); EntityForArrayList entity2 = new EntityForArrayList(2, "lifei", 1); myList.add(entity1); myList.add(entity2); List<EntityForArrayList> myList2 = new ArrayList(); EntityForArrayList entity3 = new EntityForArrayList(3,"life",1); //添加单个元素的方法 myList2.add(entity3); //添加集合的方法 myList2.addAll(myList); // for (EntityForArrayList entityForArrayList : myList2) { // System.out.println(entityForArrayList); // } EntityForArrayList entity4 = new EntityForArrayList(4, "forAdd", 0); //在指定位置之后添加元素 myList2.add(1, entity4); // for (EntityForArrayList entityForArrayList : myList2) { // System.out.println(entityForArrayList); // } EntityForArrayList entity5 = new EntityForArrayList(5, "forChange", 1); myList2.set(1, entity5); /** * 背景:拿到一个集合,要求删除集合中集合id为5的实体 * 这样我们就可以进行遍历。遍历过程中,进行检测。然后直接删除。逻辑上是没有问题的。 * 但是当我们这样书写的时候会报出一个 ConcurrentModificationException。 * 举个例子来说明这个问题。 * 现在有4颗糖果,分别是红橙蓝紫四个颜色。要求得到一个集合里面没有橙色糖果。我们要做的事情是去遍历给出的糖果,作出判定——这个糖果是不是橙色的。 * 如果是,就拿出来。当我们要把这颗糖果拿出来的时候,我们要遍历的集合的个数已经发生了改变,不再是开始给出的包含4颗糖果的集合了。遍历属于单独的对于整体的元素的个数的一个把握。 * 如果数量变了,那么迭代就可能发生异常。试想,假设这个任务是分给两个小朋友做得。一个小朋友负责遍历糖果,另一个小朋友负责判定是否橙色并取出。 * 如果做遍历的小朋友,每次遍历,糖果的数量都是不确定的,那么他在数起来的时候,就会出现问题。所以遍历的时候不能更改元素的个数。添加也会报出异常。 * */ /*for (EntityForArrayList entityForArrayList : myList2) { if(entityForArrayList.getId()==5){//当当前元素为非最后一个的时候还不会报ConcurrentModificationException异常 myList2.remove(entityForArrayList); } System.out.println(entityForArrayList); }*/ /** * concurrentModificationException 演示2: * 添加元素时候,因为让小朋友遍历的时候数着数着,偷偷往集合里面添加元素,那么他也有可能数着数着数乱了。所以这种情况下也是会爆出异常的。 */ /*int i =0; for (EntityForArrayList entityForArrayList : myList2) { i++; if(i==2){ myList2.add(entity4); } System.out.println(entityForArrayList); }*/ /** * 当然如果 只是单纯的换糖果是不会影响的。【当然只是不影响遍历,对于颜色的要求还要另外写逻辑实现,要判断用来替换的糖果是否是橙色的】 */ int j =0; for (EntityForArrayList entityForArrayList : myList2) { j++; if(j==2){ myList2.set(2,entity4); } System.out.println(entityForArrayList); } System.out.println("-------------"); System.out.println(myList2.get(2)); System.out.println(myList2.size()); } }