文章目录
- 增强For循环
- ArrayList的嵌套使用举例
- Vector集合
- LinkedList集合
- List三个子实现类的特点:
- 一个小练习:
- Set集合
- HashSet的add方法的底层源码
增强For循环
- JDK5之后提供了特性:
- <引用类型>泛型,静态导入,增强for,可变参数,自动拆装箱
- 增强for的格式:
for(数据类型 变量名 : 数组对象/集合对象(使用最多)){
输出变量名即可
}
- 作用:是替代迭代器使用,简化遍历集合的书写格式!
- 注意事项:
1)增强for主要用在集合中,数组一般使用的时候普通for
2)前提条件:
要使用增强for循环的话,必须保证该集合不能为null,否则就会出现空指针
NullPointerException
解决方案:
针对该对象非空判断即可!
/*
* 需求:
* 遍历List集合,存储自定义对象并遍历<Student>
* 5种方式
*
* */
public class ForeachTest {
public static void main(String[] args) {
//创建一个List集合对象
List<Student> list = new ArrayList<Student>() ;//new ArrayList<Student>() :jdk7以后:泛型推断,建议和前面集合泛型保持一致
//创建几个学生对象
Student s1 = new Student("文章", 35) ;
Student s2 = new Student("马伊琍", 44) ;
Student s3 = new Student("姚笛", 28) ;
Student s4 = new Student("黄晓明", 35) ;
Student s5 = new Student("邓超", 37) ;
//添加
list.add(s1) ;
list.add(s2) ;
list.add(s3) ;
list.add(s4) ;
list.add(s5) ;
//方式1
Object[] objs = list.toArray() ;
for(int x = 0 ; x < objs.length ; x ++) {
Student s = (Student)objs[x] ;
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("---------------------------------");
//方式2:Collection的迭代器
Iterator<Student> it = list.iterator() ;
while(it.hasNext()) {
Student s = it.next() ;
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("--------------------------------");
//方式3:list get方法和size()集合
for(int x = 0 ; x < list.size() ; x ++) {
Student s = list.get(x) ;
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("-------------------------------");
//方式4:列表迭代器
ListIterator<Student> lit = list.listIterator() ;
while(lit.hasNext()) {
Student s = lit.next() ;
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("-------------------------------");
//增强for循环
for(Student s : list) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
ArrayList的嵌套使用举例
* ArrayList集合实现了List接口!
* 可以存储重复元素,存储和取出一致(有序的)!
*
* ArrayList:单线程程序中考虑执行效率,优先采用!
* 应用场景:
* 网络聊天室 查看在线好友列表
* 张三 (客户端 Socket) ArrayList<Socket>
* 李四
* 王五
* 在一些嵌套中使用
* HashMap<String,ArrayList<String>> :Map集合嵌套ArrayList
*
* ArrayList<ArrayList<Student>> :ArrayList嵌套ArrayList
*
* 需求:
* 有很多个班级,每一个班级看成ArrayList<Student>,
* 这多个班级组成大的集合:ArrayList<ArrayList<Student>>
* 给每一个班级中添加一些学生,遍历 ArrayList<ArrayList<Student>>
public class ArrayListDemo {
public static void main(String[] args) {
//创建一个大的集合
ArrayList<ArrayList<Student>> bigList =
new ArrayList<ArrayList<Student>>() ;
//三个子集合:ArrayList<Student>
ArrayList<Student> list1 = new ArrayList<Student>() ;
list1.add(new Student("刘备", 39)) ;
list1.add(new Student("关羽", 35)) ;
list1.add(new Student("张飞", 30)) ;
//创建第二个子集合
ArrayList<Student> list2 = new ArrayList<Student>() ;
list2.add(new Student("曹操",44)) ;
list2.add(new Student("蒋干",36)) ;
list2.add(new Student("黄忠",45)) ;
ArrayList<Student> list3 = new ArrayList<Student>() ;
list3.add(new Student("宋江",50)) ;
list3.add(new Student("林冲",30)) ;
list3.add(new Student("鲁智深",45)) ;
//将三个集合添加到大集合中
bigList.add(list1) ;
bigList.add(list2) ;
bigList.add(list3) ;
//增强for遍历集合
//ArrayList<ArrayList<Student>>
for(ArrayList<Student> list: bigList) {
for(Student s :list) {
System.out.println(s.getName()+"\t"+s.getAge());
}
}
}
}
Vector集合
- Vector集合:
底层数组结构:查询快,增删慢
线程安全的---->同步的---->执行效率低!
- public boolean add(Object e):传统添加元素的方法
- 特有功能:
public void add(int index, E element):插入元素
public Enumeration<Object> elements() --- 相当于:Iterator iterator()
该接口有两个方法
boolean hasMoreElements():判断是否有下一个元素-----> 相当于:boolean hasNext()
Object nextElement():获取一个元素 -----> 相当于:next()
public Object elementAt(int index):通过角标获取指定的元素---->相当于:Object get(int index)
elementAt()+size() :vector的普通for遍历方式
- Enumeration和Iterator功能是重复的
- 场景呢:
IO流:合并流 SequenceInputStream 可以将多个文件内容读出来复制到指定文件中!
操作的输入流!
LinkedList集合
- LinkedList集合的特点:
底层数据结构是链接列表,查询慢,增删快
线程不安全的---不同的---->执行效率高!
- 应用场景:
网站中 记录用户浏览过商品足迹 (Web技术:Cookie/Session)
- 特有功能
- 添加
public void addFirst(Object e):将该元素添加到列表的开头!
public void addLast(Object e):将该元素添加到列表的末尾!
- 删除
public Object removeFirst():删除列表第一个
public Object removeLast():删除列表最后一个
- 获取
public Object getFirst():获取第一个
public Object getLast() :获取第二个
List三个子实现类的特点:
ArrayList
底层数据结构是可变数组结构: 查询快,增删慢
ArrayList底层可变数组:
ArrayList(int initialCapacity) :通过初始化容量构造ArrayList集合
默认容量大小:capacity:10个
ArrayList()---->通过初试容量大小判断是否构造一个新Object[] 数组对象
结论:它的扩容机制 ---1.5倍扩容
线程角度:
线程不安全的类----不同步的----执行效率高!
单线程程序中,通常没有告诉使用什么集合的时候,优先采用的是ArrayList集合!
Vector :底层数据数组结构(对象数组)
查询快,增删慢
线程角度:
线程安全的类 ---->同步的----->执行效率低
多线程程序中要考虑安全问题,使用Vector
LinkedList:
底层数据结构:链接列表实现(链表)
线程角度:
线程不安全-----不同步---->执行效率高
特有功能:
可以模拟栈结构的:先进后出!
线程安全的类
StringBuffer/Vector
一个小练习:
* 使用集合模拟用户登录,注册功能 (没有明确告诉集合类型,默认使用ArrayList集合)
*
*
* 分析:
* 登录,注册功能
* 1)分包:
* com.xx.entity: 实体类
* User:用户
* 属性私有化:username ,password
* 提供对应setXXX()/getXXX()....
*
* com.xx.dao: 数据访问接口层
* UserDao
* 注册方法
* void regist(User user);
*
* //用户输入用户和密码之后,选择注册功能,直接注册成功
* boolean isLogin(String username,String password) ; //登录功能
*
* com.xx.dao.impl:数据访问接口实现层
* UserDaoImpl
* private static ArrayList<User> array = new ArrayList<User>();
*
* 需要用对注册/登录重写 (业务的功能)
*
*
* 注册功能
* 将用户录入的姓名和用户名,封装到User对象中,然后将User对象存储到ArrayList集合中
* ArrayList<User>
*
* public void regist(User user){
* //创建User对象
* //需要的ArrayList集合对象ArrayList<User>
* }
*
* //登录功能
* public boolean isLogin(String username,String password){
* //业务:
* 使用增强for遍历ArrayList集合
* //获取到当前集合中存在用户名和密码,和键盘录入username和password对比
* 如果一致
* 返回值true
* 否则:
* false
* }
*
*
*
*
* com.xx.user.test
* UserTest
* while(true){
* 针对用户不同的选择,执行不同的业务逻辑
* --------------欢迎访问xxx系统----------------
* "1,注册"
* "2,登录"
* "3,退出"
*
* 使用接口多态;UserDao ud = new UserDaoImpl() ;
*
* //创建键盘录入对象
* //录入数据:String
* switch(变量名){
* case "1":
* //注册功能
* //录入用户名和密码:
* ud调用regist(传入封装后的User对象);
* //提示"用户注册成功"
* Syste.exit(0) ;//结束jvm
* //break ;
* case "2" :
* //登录功能
* //录入用户名和密码:
* boolean flag = ud调用isLogin(传入用户名和密码);
* //登录成功,开始玩数字游戏!
*
* break ;
*
* case "3":
* default:
* //退出
* Syste.exit(0) ;
* }
Set集合
Set集合的特点:
元素是不重复的,无序的!(存储和取出不一致,取决于底层HashMap实例)
- 子实现类
HashSet
TreeSet
存储自定义对象,必须重写hashcode()和equals()
HashSet的add方法的底层源码
interface Collection{}
interface Set extends Collection{}
class HashSet .... implements Set{
//成员位置
//transient:跟接口:serializable (map变量不会被序列化) IO流中讲
private transient HashMap<E,Object> map;
//无参构造方法:
public HashSet() {
map = new HashMap<>();//创建HashMap集合对象
}
//添加功能
public boolean add(E e) { //"hello","world","world","java"
return map.put(e, PRESENT)==null;
}
}
class HashMap<K,V> ..... implements Map<K,V>{
//map集合:双列集合的添加功能
public V put(K key, V value) { //k = "hello","world","world","java"
return putVal(hash(key), key, value, false, true);
}
//hash方法
//HashSet的add方法依赖于HashMap的put方法
//---->hashCode():首先比较是:对象的哈希码值是否相同
static final int hash(Object key) {//每一个元素
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//添加元素并进行一些系列判断
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {//k 传进来的元素:字符串/自定义对象
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
//如果上面的对象的哈希码一样的话,比较成员信息是否相同:
//依赖于equals()方法
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
//....
//....
//HashSet集合add方法
依赖于:Map集合put方法
依赖于:HashCode()和equals方法()
HashSet<String> :String类会重写Object的equals方法
每一个字符串(英文的):hash码值是不同的
}
}
ash &&
//如果上面的对象的哈希码一样的话,比较成员信息是否相同:
//依赖于equals()方法
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
//…
//…//HashSet集合add方法
依赖于:Map集合put方法
依赖于:HashCode()和equals方法()
HashSet<String> :String类会重写Object的equals方法
每一个字符串(英文的):hash码值是不同的
}}