java中HashMap、ArrayList、HashSet的存储原理及遍历方式汇总

一、HashMap类

        1、底层存储方式:

             1.1   HashMap在JDK1.7之前底层是用数组+链表的方式存储的;在JDK1.8之后底层是用数组+链表+红黑树存储的。

             1.2  HashMap里面实现了一个静态内部类Entry。

             1.3  Entry的属性有key,value,next,hash。Entry存储的是key-value键值对。

             1.4  HashMap存储是无序的。

             1.5  HashMap可以存储null值。

        2、遍历方式有4种:

 
 
public static void main(String[] args) {  
	 Map<String, String> map = new HashMap<String, String>();  
	 map.put("1", "test1");  
	 map.put("2", "test2");  
	 map.put("3", "test3");  
	   
	 //第一种方式:使用使用较多  通过Map.keySet遍历key和value
	  for (String key : map.keySet()) {  
	   System.out.println("获取Map中key的值 "+ key);  
	   System.out.println("根据key获取value的值 " + map.get(key));
	  }  
		
	  //第二种  "通过Map.entrySet使用iterator遍历key和value:"
	  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();  
	  while (it.hasNext()) {  
	   Map.Entry<String, String> entry = it.next();  
	   System.out.println("获取Map中key的值 " + entry.getKey());
	   System.out.println("获取value的值 " + entry.getValue());  
	   
	  }  
		
	  //第三种:使用比较多,推荐使用,尤其是容量大时   
	  for (Map.Entry<String, String> entry : map.entrySet()) {  
	   System.out.println("获取Map中key的值" + entry.getKey());
	   System.out.println("获取value的值" + entry.getValue());  
	  }  
	  
	  //第四种:使用很少,不推荐  "通过Map.values()遍历所有的value,但不能遍历key"
	  for (String v : map.values()) {  
	   System.out.println("value= " + v);  
	  } 
}  

二、ArrayList类

        1、概述:

             1.1  ArrayList是基于数组实现的,是动态数组,容量能自动增长。

             1.2  ArrayList线程不安全,只能在单线程下使用。多线程环境下使用Collections.synchronizedList(List)返回一个线程安全的ArryayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

              1.3   ArrayList实现了Serializable接口,因此支持序列化传输;ArrayList实现了RandomAccess接口,因此支持通过下标序号进行快速访问;ArrayList实现了Cloneable接口,因此支持被克隆。

               1.4  通过ensureCapacity增加ArrayList类的容量。

               1.5  无参构造方法构造的容量默认为10,带有Collection参数的构造方法,将collection转化为数组赋给ArrayList的实现数组elementData

            1.6   ArrayList实现中调用了Arrays.copyof()方法,该方法就是在内部创建一个长度为newlength的数组;调用System.arraycopy方法,该方法被标记了native,可以保证数组内元素的正确复制和移动,适合批量处理数组,效率较高。

               1.7    ArrayList基于数组实现,通过下标索引查找指定位置的元素,因此查询效率高;插入和删除效率低。

               1.8    ArrayList将元素的值分为null和不为null两种情况处理,支持null存储。

               1.9   ArrayList是有序的,可以包含重复数据。

        2、遍历方式分为5种:

public class Test {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList<Integer>();
        int n=100;
        while (n>0){
            list.add(n);
            n--;
        }
        //1.效率最高,也是官方推荐用法
        for (int i = 0; i < list.size(); i++) {
            System.out.print(i);
        }
        //2.底层通过Iterator操作底层数组,其中remove()方法迭代过程中删除元素的唯一方法。
        for (Iterator it=list.iterator();it.hasNext()){
            System.out.print(it.next());
        }
        //3.增强for循环底层用Iterator实现的,相当于增强for循环是在第二种方法外包了一层,效率稍微低
        for (int i:list){
            System.out.print(i);
        }
        //4.底层源码是通过增强for实现的,相当于在 增强for外又包了一层,效率较低(JDK5特性)
        list.forEach(item -> {});
        //5.支持多线程操作
        list.stream().forEach(item -> {});
    }
}

三、Set类

        1、概述

                1.1   hashSet底层是基于hashMap存储的。

                1.2   hashSet存储的元素是无序的,更不能保证顺序恒久不变。

                1.3   hashSet不是不同步的,需要外部保持线程之间的同步问题。

                1.4   hashSet允许存储null值。

                1.5   hashSet不能存储重复值。

                1.6   hashSet存储值,必须覆盖hashCode()方法和equals()方法。

        2、遍历方式有2中:

public class Test{
    public static void main(String[] args) {
        Set<String> set=new HashSet<String>();
        for (int i = 0; i <5 ; i++) {
            set.add(""+i);
        }

        //1.迭代遍历(针对字符串)
        Iterator<String> it=set.iterator();
        while (it.hasNext()){
            String str=it.next();
            System.out.print(str);
        }
        //或者
        for (Iterator it2=set.iterator();it2.hasNext();){
            System.out.print(it2.next());
        }

        //2.for遍历(针对字符串)
        for (String s:set){
            System.out.print(s);
        }
        //3.遍历对象并不能重复
        //定义实体类
        public class User{
            private String name;
            private String age;
            //get和set方法
            public String getName() {return name;}
            public void setName(String name) {this.name = name;}
            public String getAge() {return age;}
            public void setAge(String age) { this.age = age; }
            //重写toString方法
            @Override
            public String toString() {
                return "User{" +
                        "name='" + name + '\'' +
                        ", age='" + age + '\'' +
                        '}';
            }
            //重写equals方法,判断的准则是 name和age
            @Override
            public boolean equals(Object o) {
                //如果值相等就返回
                if (this == o) return true;
                //快速排除非User类和null
                if (!(o instanceof User)) return false;
                //强制转换
                User user = (User) o;
                if (name != null ? !name.equals(user.name) : user.name != null) return false;
                return age != null ? age.equals(user.age) : user.age == null;
            }
            //重写hashCode方法
            @Override
            public int hashCode() {
                int result = name != null ? name.hashCode() : 0;
                result = 31 * result + (age != null ? age.hashCode() : 0);
                return result;
            }
        }
        //遍历存储的对象并保证不重复
        Set<User> set2=new HashSet<User>();
        set2.add(new User("张三","20"));
        set2.add(new User("李四","30"));
        for (Iterator<User> it3=set2.iterator();it3.hasNext();){
            System.out.print(it3.next());
        }
    }
}

猜你喜欢

转载自blog.csdn.net/u013226533/article/details/79628477