您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

集合框架之List、Array List、set、Map

List

List是java集合框架种最常见的一个集合接口,直接从Collection继承而来;List集合是一个有序集合(内部的元素顺序按照添加顺序存储);List接口中包含几个常用的实现类:ArrayList、LinkedList、Vector(JDK1.0)

  • ArrayList:(数组列表),基于动态数组的实现

  • LinkedList: (链表),基于链表的实现

  • Vector:(数组列表),基于动态数组的实现

ArrayList

Arraylist是一个基于数组的动态数组实现,内部可以存储任何的数据类型的元素,提供了一系列的API用于简单的访问列表数据。

ArrayList基本使用

public class ArrayListDemo {
​
    public static void main(String[] args) {
    
        List<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(20);
        list.add(30);
        list.add(40);
        list.add(50);
        list.add(60);
        
        List<Integer> list2 = new ArrayList<>();
        list2.add(100);
        list2.add(200);
        
        list.addAll(list2);
        
        System.out.println(list.contains(100));
        
//      for (Integer integer : list) {
//          list.remove(integer);
//      }
        
        //不允许在对集合遍历时调用集合的remove方法更改元素,会抛出一ConcurrentModificationException
        //如果需要在遍历时删除,因该调用通过集合获取的迭代器对象自生的remove方可更改
        Iterator<Integer> it = list.iterator();
        while(it.hasNext()){
            int i = it.next();
            //remove前要确保next()获取过元素,否则会出现IllegalStateException
            it.remove();
        }
    }
​
}
​

注意事项:

//不允许在对集合遍历时调用集合的remove方法更改元素,会抛出一个ConcurrentModificationException
//      for (Integer integer : list) {
//          list.remove(integer);
//      }
        
        //如果需要在遍历时删除,因该调用通过集合获取的迭代器对象自生的remove方可更改
        Iterator<Integer> it = list.iterator();
        while(it.hasNext()){
            int i = it.next();
            //remove前要确保next()获取过元素,否则会出现IllegalStateException
            it.remove();
        }
    }

基于sort()方法使用Comparator接口实现集合排序

JDK1.8中List接口新增了默认方法sort用于实现对集合排序,方法内部只需要传入一个排序规则(实现Comparator接口)即可实现对集合元素排序,如下案例:

排序比较器:

/**
    排序比较器,通过继承Comparator接口并实现compare方法
*/
public class MyComparator implements Comparator<String>{
    
    /*
        方法内部需要传入两个被比较的对象,数据类型跟接口泛型一直,方法
        的返回值为int值,集合的sort方法会自动根据该返回结果决定如何实现对元素
        的排序
    */
    @Override
    public int compare(String a, String b) {
        return a.compareTo(b);
    }
​
}
​

测试类

public class TestSort {
​
    public static void main(String[] args) {
        
        ArrayList<String> names = new ArrayList<>();
        names.add("tom");
        names.add("jarry");
        names.add("admin");
        names.add("allen");
        names.add("kobe");
        //执行排序      
        names.sort(new MyComparator());
        
        for(String n:names){
            System.out.println(n);
        }
    }
​
}
​

执行结果:

[admin, allen, jarry, kobe, tom]

对于无需反复使用的比较器,可无需单独定义比较器类,直接在sort方法中使用匿名内部类的写法即可完成相同的排序功能:

public class TestSort {
​
    public static void main(String[] args) {
        
        ArrayList<String> names = new ArrayList<>();
        names.add("tom");
        names.add("jarry");
        names.add("admin");
        names.add("allen");
        names.add("kobe");
        //匿名内部类实现排序规则(回调机制callback)
        names.sort(new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return a.compareTo(b);
            }
        });
    }
​
}
​

JDK8之后新增的lambda表达式可以进一步简化匿名内部类的写法,如下:

import java.util.ArrayList;
​
public class TestSort {
​
    public static void main(String[] args) {
        
        ArrayList<String> names = new ArrayList<>();
        names.add("tom");
        names.add("jarry");
        names.add("admin");
        names.add("allen");
        names.add("kobe");
        //lambda表达式
        names.sort((a,b)->a.compareTo(b));
        
        
        
        ArrayList<Integer> list = new ArrayList<>();
        list.add(8);
        list.add(4);
        list.add(5);
        list.add(2);
        list.add(1);
        list.add(9);
        list.add(7);
        //lambda表达式
        list.sort((a,b)->a-b);
        System.out.println(list);
    }
​
}
​

中文排序(扩展)

由于在实际开发中排序的规则多变,比如,在中文环境下需要对中文字符串按照汉语拼音的字母表顺序排列,因此,将中文字符串转换为汉语拼音就成为了排序的关键因素;

Pinyin4J插件可以帮助我们实现将中文字符串转换为汉语拼音,使用前需要先将插件包(pinyin4j-XX.jar)加载到项目中(buildPath),具体使用如下:

public class TestPinyin {
​
    public static void main(String[] args) {
        
        //将指定的字符转换为汉语拼音
        String[] str = PinyinHelper.toHanyuPinyinStringArray('中');
        //由于字符可能存在多种读音,因此返回为各种读音的字符串数组
        for (String s : str) {
            System.out.println(s);
        }
        
        String name = "张三疯";
        //下面的例子演示了如何将“张三疯”转换为zhang1san1feng1的过程
        String pinyin= "";
        for (int i = 0; i < name.length(); i++) {
            char n = name.charAt(i);
            String[] p = PinyinHelper.toHanyuPinyinStringArray(n); 
            pinyin += p[0];
        }
        System.out.println(pinyin); //zhang1san1feng1
    }
}

通过对以上代码的使用,再结合之前的sort方法和Comparator接口即可轻松实现对中文的排序,示例如下:

Student.java

public class Student {

	private String name;
	private int age;
	private double score;
	
	public Student() {
		// TODO Auto-generated constructor stub
	}
	
	public Student(String name, int age, double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	
}

TestStudent.java

import java.util.ArrayList;
import java.util.Comparator;

import net.sourceforge.pinyin4j.PinyinHelper;

public class TestStudent2 {

	public static void main(String[] args) {
		
		ArrayList<Student> list = new ArrayList<>();
		list.add(new Student("张三丰", 19, 55));//zhang	5
		list.add(new Student("苍老师", 20, 32));//cang	1
		list.add(new Student("牛德华", 18, 48));//niu		4
		list.add(new Student("马老师", 21, 98));//ma		3
		list.add(new Student("柴老师", 23, 101));//chai	2
		//排序实现
		list.sort((a,b)->{
				//分别获取要比较的两个学生的姓名
				String name1 = a.getName();//zhang1san1feng1
				String name2 = b.getName();//cang1lao3shi1
				//声明变量存储转换之后汉语拼音
				String p1 = "";
				String p2 = "";
				//将汉字转拼音
				for (int i = 0; i < name1.length(); i++) {
					p1 += PinyinHelper.toHanyuPinyinStringArray(name1.charAt(i))[0];
				}
				for (int i = 0; i < name2.length(); i++) {
					p2 += PinyinHelper.toHanyuPinyinStringArray(name2.charAt(i))[0];
				}
				//比较
				return p1.compareTo(p2); 
		});
		
		for (Student s : list) {
			System.out.println(s);
		}
	}
}

Set

Collection接口还提供了另一个子接口Set,Set是一个无序集合,元素的存储顺序不是按照添加顺序存储(具体存储顺序跟使用的实现类有关);因为元素的存储是无序的,因此无法像List一样通过索引获取元素,所以对于Set集合中元素的获取只能通过迭代器进行迭代;另外Set集合中不允许出现重复的元素(不允许存在e1.equals(e2)),实际上是后出现的元素会覆盖原来存在的。

Set集合有两个常见的实现:

  1. HashSet:基于散列算法(Hashtable)实现的元素存储顺序

  2. TreeSet:基于二叉树中红黑树的实现,元素的排序方式需要通过实现Comparable或者Comparator接口完成

public class HashSetDemo {
​
    public static void main(String[] args) {
        
        //无序(不按照添加顺序存储),不允许重复
        HashSet set = new HashSet();
        set.add("hello");
        set.add("rose");
        set.add("123");
        set.add(true);
        set.add(100);
        set.add(3.14);
        set.add("rose");
        set.add(null);
        System.out.println(set.size());
        System.out.println(set);
        
        for (Object obj : set) {
            System.out.println(obj);
        }
        System.out.println("----------------");
        Iterator it = set.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
​
}

HashSet和TreeSet区别?

HashSet:基于Hash表实现的元素存储,内部元素的排序按照hash表中的地址进行排序,内部允许null值存在,但是不允许重复的元素,如果一旦出现重复的元素(此时hash值是已经存在的情况,不会将新的元素存储)。

TreeSet:基于树的实现,内部元素的排序需要通过提供排序比较器(Comparable,Comparator)进行实现;内部的元素必须是Comparable实现类(或者在创建TreeSet对象时提供Comparator比较器),并且由于比较器内部会使用到集合中的元素,因此元素不允许为null(会导致NullPointerException).

Map

Map接口是JDK1.2新增集合框架中的一种容器,Map集合内部的元素存储采用键值对(Key-Value)结构,key不允许重复,另外每一个key都会对应一个value对象;Map集合有三个常见实现类:

  1. HashMap

  2. TreeMap

  3. Hashtable

HashMap使用

public class HashMapDemo {
​
    public static void main(String[] args) {
        
        HashMap map = new HashMap();
        map.put(3.14, Math.PI);
        map.put(1, "hello");
        map.put(true, new String("true"));
        map.put("a", "admin");
        
        System.out.println(map);
        
        System.out.println(map.get("a"));
        
        //获取Map中键值对的set集合
//      Set set = map.entrySet();
//      for (Object obj : set) {
//          System.out.println(obj);
//      }
        
        //获取Map集合中键集(keys)
        Set set = map.keySet();
        for (Object key : set) {
            System.out.println(key+"-----"+map.get(key)); 
        }
        
        //获取Map集合中值集(values)
        Collection c = map.values();
        for (Object v : c) {
            System.out.println(v);
        }
        
        
        //聊天室,要显示每个ip地址对应的用户的昵称?
        Map<String,String> users = new HashMap<>();
        users.put("192.168.4.254", "狗蛋");
        users.put("192.168.4.151", "翠花");
        users.put("192.168.4.168", "旺财");
        users.put("192.168.4.76", "来福");
        users.put("192.168.4.55", "傻根");
        //根据key移除指定的元素(key-value对)
        users.remove("192.168.4.168");
        
        System.out.println(users);
        //获取集合中元素的个数
        System.out.println(users.size());
    }
​
}
​

HashMap、Hashtable、TreeMap的区别?

HashMap:是基于hash表的实现,是Map接口的一个实现类,内部的元素存储顺序是根据key的hash地址进行排序,因此,元素的顺序存储顺序可能跟添加的顺序不一致;HashMap使用链表加数组共同来实现元素存储;HashMap允许空键值出现,但是不允许重复的键存在(值可以重复);HashMap是线程不同步的实现,因此在操作数据时效率较高,但是线程并发是不能保障数据的一致性。如果多线程并发下使用建议使用:java.util.concurrent.ConcurrentHashMap****

Hashtable:Hashtable是集合框架出现之前的键值对集合解决方案,从Dictionary类(JDK1.0)继承而来,在JDk1.2出现Map接口后,Hashtable又从改接口实现,Hashtable不允许空键值出现,该类的实现是线程同步,因此在多线程并发操作时对数据的一致性有保障,但是效率低。

TreeMap:是基于二叉树中的红黑树实现,元素的存储按照键的自然顺序排序(键必须实现Comparable接口,或者在创建TreeMap对象时指定的Comparator比较器),TreeMap中的键必须是相同的数据类型,并且不允许空元素出现,同HashMap一样,TreeMap也是线程不同步的实现。

Collections类

Collections类是是一个用于对集合进行一些常规操作的工具类(排序,查找,反转等),内部包含的都是静态方法.

public class CollectionsDemo {
​
    public static void main(String[] args) {
    
        List<String> list = Arrays.asList("tom","jack","rose","lucy","lily");
        List<String> list2 = Arrays.asList("狗蛋","傻根","旺财","来福");
        System.out.println(list);
        
        //二分查找
        int pos = Collections.binarySearch(list, "rose");
        System.out.println(pos);
        
        //将第二个集合拷贝到第一个集合中(第一个集合中的元素会被覆盖)
//      Collections.copy(list, list2);
//      System.out.println(list);
        
        Collections.emptyList();
        
        String s = Collections.max(list);
        System.out.println(s);
        
        //反转集合
        Collections.reverse(list);
        System.out.println(list);
        
        //洗牌
        Collections.shuffle(list);
        System.out.println(list);
        
        //排序
        Collections.sort(list);
        System.out.println(list);
    }
​
}

Collection、Collections、Connection什么区别?

Collection:JDK1.2之后出现的集合框架的顶层接口

Collections:跟随集合框架共同出现的一个用处理集合(排序,查找等)相关的工具类

Connection:

排序解决方案Comparable&Comparator

目标类需要实现Comparable接口

public class User implements Comparable<User>{
​
    private String name;
    private int age;
    
    public User() {
        // TODO Auto-generated constructor stub
    }
    
    public User(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public int compareTo(User u) {
        return this.age - u.age;
    }
​
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
    
}
​

测试类

public class Test {
​
    public static void main(String[] args) {
        
        List<User> list = Arrays.asList(
                    new User("tom", 19),
                    new User("jack", 18),
                    new User("curry", 26),
                    new User("james", 16),
                    new User("kobe", 39),
                    new User("wade", 22),
                    new User("zark", 29)
                );
        
        //使用该方法时,集合中的类型需要实现Comparable接口,并实现comparaTo方法
        Collections.sort(list);
        //使用该方法时,集合中的类型无需实现Comparable接口,但需要通过第二个参数
        //指定排序比较器(Comparator)并实现比较器中的compare(t1,t2)方法
        Collections.sort(list,(a,b)->a.getName().compareTo(b.getName()));
        
        for (User u : list) {
            System.out.println(u);
        }
        
    }
​
}
​

分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进