java 集合

在这里插入图片描述

1. list:(有序可重复)

  • ArrayList:底层实现是数组,但是没有定义具体的长度和大小,有下标,所以查询快,增删慢,线程不安全

  • LinkedList: 底层是链表,因为有指针所以增删快查询慢,线程不安全

  • Vector:底层是数组,线程安全,有下标所以查询快增删慢,有synchronized修饰,现已被ArrayList替代

1.1. list集合遍历
	for(int i = 0; i < list.size(); i++) {
			Student s = (Student)list.get(i);
		}
		
	ListIterator lit = list.listIterator();			//获取迭代器(List集合特有的)
		while(lit.hasNext()) {
			String str = (String)lit.next();			//向下转型
			if("world".equals(str)) {
				//list.add("javaee");						//遍历的同时在增加元素,并发修改ConcurrentModificationException
				lit.add("javaee");
			}
		}
		
	ListIterator lit = list.listIterator();			//获取迭代器
		while(lit.hasNext()) {
			System.out.println(lit.next()); 			//获取元素并将指针向后移动
		}
		
		while(lit.hasPrevious()) {
			System.out.println(lit.previous()); 		//获取元素并将指针向前移动
		}

2. Set:(无序不重复)

  • HashSet:底层是hash表结构,实现了set接口,其实是基于hashMap实现的,不能有null值,在添加数据时(add方法),会调用对象的hashcode()方法在set中去查找,比较要添加的值和set中的值若是hash值相等,若是相等则用equals方法比较,如果不相等,则添加(说明没有重复的值)

  • TreeSet:底层是二叉树结构,不可以存重复对象,根据数据自身进行排序,如果没有可比性,则实现comparable接口重写compareTo方法(该方法是使某个对象具有可比性),也可实现compartor接口重写compare方法(该方法是使某个集合具有可比性)

2.1. Set集合,无索引,不可以重复,无序(存取不一致)
HashSet<String> hs = new HashSet<>();					//创建HashSet对象
		boolean b1 = hs.add("a");
		boolean b2 = hs.add("a");						//当向set集合中存储重复元素的时候返回为false
		hs.add("b");
		hs.add("c");
		hs.add("d");
2.2. LinkedHashSet是HashSet的子类,底层是链表实现的,有序
LinkedHashSet<String> lhs = new LinkedHashSet<>();
		lhs.add("a");
		lhs.add("a");
		lhs.add("b");
2.3. TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一
 * 当compareTo方法返回0的时候集合中只有一个元素
 * 当compareTo方法返回正数的时候集合会怎么存就怎么取
 * 当compareTo方法返回负数的时候集合会倒序存储
	TreeSet<Person> ts = new TreeSet<>();
		ts.add(new Person("zhangsan", 23));
		ts.add(new Person("lisi", 13));
		ts.add(new Person("wangwu", 33));
		ts.add(new Person("zhaoliu", 43));
		
	TreeSet<String> ts = new TreeSet<>(new CompareByLen());	
		ts.add("aaaaaaaa");
		ts.add("z");
		ts.add("wc");
		ts.add("nba");
		
	class CompareByLen /*extends Object*/ implements Comparator<String> {
	
		@Override
		public int compare(String s1, String s2) {		//按照字符串的长度比较
			int num = s1.length() - s2.length();		//长度为主要条件
			return num == 0 ? s1.compareTo(s2) : num;	//内容为次要条件
		}
		
	}

3. Map:(存键值对)

  • HashMap:底层是哈希表(数组+链表)结构,线程不安全,可以存一个null键和多个null值,若要线程安全则Collections.synchronizedMap()方法,在添加新值的时候(put)会去计算将添加key值的hashCodehashCode%length = i,要存的entry,若此时entry上已经有值了那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

  • HashTable:底层是哈希表(数组+链表)结构,线程安全,不可以存null键或者null

  • TreeMap:底层实二叉树结构,可以存重复对象,实现comparable接口重写compareTo方法(该方法是使某个对象具有可比性),也可实现compartor接口重写compare方法(该方法是使某个集合具有可比性)

3.1. Map集合的迭代

		//获取所有的键
		Set<String> keySet = map.keySet();			//获取所有键的集合
		Iterator<String> it = keySet.iterator();	//获取迭代器
		while(it.hasNext()) {						//判断集合中是否有元素
			String key = it.next();					//获取每一个键
			Integer value = map.get(key);			//根据键获取值
			System.out.println(key + "=" + value);
		}
		
		//使用增强for循环遍历
		for(String key : map.keySet()) {			//map.keySet()是所有键的集合
			System.out.println(key + "=" + map.get(key));
		}


		//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
		Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
		//获取每一个对象
		Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
		while(it.hasNext()) {
			//获取每一个Entry对象
			Map.Entry<String, Integer> en = it.next();	//父类引用指向子类对象
			//Entry<String, Integer> en = it.next();	//直接获取的是子类对象
			String key = en.getKey();					//根据键值对对象获取键
			Integer value = en.getValue();				//根据键值对对象获取值
			System.out.println(key + "=" + value);
		}
		
		//使用增强for循环遍历
		for(Entry<String, Integer> en : map.entrySet()) {
			System.out.println(en.getKey() + "=" + en.getValue());
		}

3.2. HashMap
		HashMap<Student, String> hm = new HashMap<>();
		hm.put(new Student("张三", 23), "北京");
		hm.put(new Student("张三", 23), "上海");
3.3. LinkedHashMap
		LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
		lhm.put("张三", 23);
		lhm.put("李四", 24);
3.4. TreeMap
public static void main(String[] args) {
		TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				int num = s1.getName().compareTo(s2.getName());		//按照姓名比较
				return num == 0 ? s1.getAge() - s2.getAge() : num;
			}
		});
		tm.put(new Student("张三", 23), "北京");
		tm.put(new Student("李四", 13), "上海");
		tm.put(new Student("赵六", 43), "深圳");
		tm.put(new Student("王五", 33), "广州");
	}

补充:

1.HashMap和TreeMap的区别
  • HashMap:数组方式存储key/value,线程非安全,允许null作为keyvaluekey不可以重复,value允许重复,不保证元素迭代顺序是按照插入时的顺序,keyhash值是先计算key的hashcode值,然后再进行计算,每次容量扩容会重新计算所以keyhash值,会消耗资源,要求key必须重写equalshashcode方法

  • TreeMap:基于红黑二叉树的NavigableMap的实现,线程非安全,不允许nullkey不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,两个相比较的key不得抛出classCastException。主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出

2.HashMap的排序
public static void main(String[] args) {
		HashMap<Integer, User> map = new HashMap<Integer, User>();
		map.put(1, new User("张三", 26));
		map.put(3, new User("李四", 32));
		map.put(2, new User("王五", 23));
		System.out.println("排序前:"+map);
		//TODO 对hashmap排序实现age字段按倒序排列
		HashMap<Integer,User> sortHashMap = sortHashMap(map);
		System.out.println("排序后:"+sortHashMap);
		
	}
	//对HashMap排序
	public static HashMap<Integer, User> sortHashMap(HashMap<Integer, User> map) {
		LinkedHashMap<Integer, User> linkedHashMap = new LinkedHashMap<>();
		
		//TODO 将map 转化成Collection
		Set<Entry<Integer,User>> set = map.entrySet();
		
		ArrayList<Entry<Integer,User>> list = new ArrayList<>(set);
		
		Collections.sort(list, new Comparator<Entry<Integer,User>>() {

			@Override
			public int compare(Entry<Integer, User> o1, Entry<Integer, User> o2) {
				//排序规则
				//前一个对象-后一个对象=正序
				return o2.getValue().getAge()- o1.getValue().getAge(); 
			}
		});
		//TODO 将list的内容添加到linkedHashMap中
		for (int i = 0; i < list.size(); i++) {
			linkedHashMap.put(list.get(i).getKey(), list.get(i).getValue());
		}
		
		return linkedHashMap;
	}
3. HashMap问答
  1. 1.7 的 HashMap的数据结构是怎么样的?
    数组 + 链表
  2. 1.7 的 HashMap怎么在链表上添加数据,在链表的前⾯还是链表的后⾯?
    「头插法」
  3. 1.7 HashMap是怎么预防和解决 Hash冲突的?
    「⼆次哈希」 + 「拉链法」
  4. 1.7 HashMap默认容量是多少?为什么是 16 可以是 15 吗?
    16,需要是 2 的幂次⽅
  5. 1.7 HashMap的数组是什么时候创建的?
    ⾸次调⽤ put
  6. 1.7 和 1.8 数据结构有什么不同?
    1.8 增加了转换为红⿊树
  7. 插⼊数据的⽅式?
    1.7 的链表从前⾯插⼊,1.8 的链表从后⾯插⼊
  8. 扩容后存储位置的计算⽅式?
    1.7 通过再次 indexFor()找到数组位置,1.8 通过⾼低位的桶直接在链表尾
    部添加
  9. HashMap什么时候会把链表转化为红⿊树?
    链表⻓度超过 8 ,并且数组⻓度不⼩于 64
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值