文章目录

  • 增强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码值是不同的
}}