本系列博客汇总在这里:Java系列_汇总


一、Set 集合(接口)

Java系列(40)——集合(下)_字符串

二、Set 集合的实现类 HashSet
  1. HashSet 实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变,此类允许使用 null 元素。
  2. List 允许重复以及存在空值(可以多个)的。

1、HashSet 集合的特点

  1. 无序性 (跟添加的顺序无关);
  2. 不能重复 ;
  3. 允许有 null,但是只能有一个;
  4. HashSet 不是线程安全的。

2、HashSet 是如何判断元素重复的

  1. Set 在添加元素的时候会拿这个元素和集合中的每一个元素做比较,如果重复了就不添加,如果没有重复就添加。
  2. 在判断字符串是否重复的时候,是调用了 String 类里面的 equals() 方法;另外,判断两个对象是否相等,必须要重写 equals 和 hashCode 方法,这两个方法都符合相等的条件才认为是相等的两个对象,如下:
    Java系列(40)——集合(下)_字符串_02
  3. 重写 equals 和 hashCode 方法
    package cn.tx.set;
    public class Person
    {
    	private int id;
    	private String name;
    	private int age;
    	// 构造器
    	public Person(int id, String name, int age)
    	{
    		super();
    		this.id = id;
    		this.name = name;
    		this.age = age;
    	}
    	public int getId()
    	{
    		return id;
    	}
    	public void setId(int id)
    	{
    		this.id = id;
    	}
    	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;
    	}
    	// 重写tostring方法
    	@Override
    	public String toString()
    	{
    		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
    	}
    	/**
    	 * 重写equal方法
    	 */
    	@Override
    	public boolean equals(Object obj)
    	{
    		// 判断是否是person类的实例
    		if (!(obj instanceof Person))
    		{
    			return false;
    		}
    		// 把传递过来的对象转换成子类
    		Person person = (Person) obj;
    		// 如果两个person的所有属性都相等我们认为是相同的person
    		if (this.id == person.id && this.name != null && person.name != null && this.name.equals(person.name) && this.age == person.age)
    		{
    			return true;
    		} else
    		{
    			return false;
    		}
    	}
    	/**
    	 * 重写hashCode
    	 */
    	@Override
    	public int hashCode()
    	{
    		//返回同一个值
    		return 1;
    	}
    }
    
    // 创建一个set的集合
    Set<Person> set = new HashSet<Person>();
    set.add(new Person(1, "诸葛亮", 26));
    set.add(new Person(2, "刘成娟", 36));
    set.add(new Person(1, "诸葛亮", 26));
    System.out.println(set);
    
    Java系列(40)——集合(下)_集合_03
三、Set 集合的实现类 LinkedHashSet
  1. LinkedHashSet 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
  2. LinkedHashSet 的方法几乎都是继承于 HashSet,不同在于 LinkedHashSet 是有序的。

LinkedHashSet 特点

  1. 有序性(添加顺序);
  2. 不能重复;
  3. 允许有null,但是只能有一个;
  4. 不是同步的(不是线程安全的,效率高)。
四、Set 集合的实现类 TreeSet

  TreeSet 可以支持自定义排序,如果 TreeSet 所存储的对象的类没有实现 Comparable 接口就会抛出异常 ClassCastException,所以我们如果想要使用TreeSet来对自定义的对象来排序必须实现Comparable 接口。

1、TreeSet 特点

  1. 元素唯一性;
  2. 可自定义排序;
  3. 不允许 null 存在;
  4. 不是线程安全。

2、自定义排序

  1. 类必须要实现一个接口 Comparable 才能做排序,之前所介绍的集合之所以没有顺序,就是因为此原因。

  2. Compare 比较两个字符串

    String str = "nbc";
    String str1 = "nbc";
    // 返回一个int类型的数字
    /*
    说明:两个字符串相互比较,从第一个字符开始比较相同索引的字符,如果第一个字符串的第一个字符比第二个字符串的第一
    个字符大(ASCII 码),就可以判断整个字符串比第二个字符串大;如果两个字符串的第一个字符相等,再去比较他们的第二个
    字符,同样遵守上述规律。
    */
    int val = str.compareTo(str1);
    System.out.println(val);
    

    ASCII 表
    Java系列(40)——集合(下)_集合_04
    Java系列(40)——集合(下)_集合_05

  3. compare 比较两个对象方法

    package cn.tx.set;
    
    public class Student implements Comparable<Student>
    {
    
    	private int stuId;
    
    	private String name;
    
    	private int age;
    
    	public int getStuId()
    	{
    		return stuId;
    	}
    
    	public void setStuId(int stuId)
    	{
    		this.stuId = stuId;
    	}
    
    	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 Student(int stuId, String name, int age)
    	{
    		super();
    		this.stuId = stuId;
    		this.name = name;
    		this.age = age;
    	}
    
    	/*
    	实现比较两个学生对象的比较 :
    	比较规则: 
    	1、先比较学号,按学号的升序排序 (o.stuId - this.stuId 为倒序 );
    	2、如果学号相等,就按照年龄比较,年龄小的在前面;
    	3、如果学号和年龄都相等,就按照名字的字符来比较。
    	*/
    	@Override
    	public int compareTo(Student o)
    	{
    		//先比较
    		int val = this.stuId - o.stuId;
    		if (val == 0)
    		{
    			val = this.age - o.age;
    			if (val == 0)
    			{
    				if (this.name != null && o.name != null)
    				{
    					val = this.name.compareTo(o.name);
    				}
    			}
    		}
    		return val;
    	}
    
    	@Override
    	public String toString()
    	{
    		return "Student [stuId=" + stuId + ", name=" + name + ", age=" + age + "]";
    	}
    }
    
    Student s = new Student(2, "zhangsan", 34);
    Student s1 = new Student(2, "lisi", 34);
    
    int i = s.compareTo(s1);
    System.out.println(i > 0 ? "s大" : "s1大");
    

    Java系列(40)——集合(下)_java_06

  4. TreeSet 示例

    // 创建一个TreeSet的集合
    Set<String> set = new TreeSet<String>();
    
    set.add("b");
    set.add("a");
    set.add("d");
    set.add("h");
    //按照 ASCII 码的大小进行排序
    System.out.println(set);
    
    Set<Integer> set1 = new TreeSet<Integer>();
    set1.add(23);
    set1.add(45);
    set1.add(2);
    set1.add(6);
    System.out.println(set1);
    
    Set<Student> set2 = new TreeSet<Student>();
    set2.add(new Student(2, "zhangsan", 23));
    set2.add(new Student(1, "zhangsan", 22));
    set2.add(new Student(3, "zhangsan", 56));
    set2.add(new Student(1, "ahangsan", 22));
    //按照 Student 类中我们规定的排序方式进行 Student 对象排序
    System.out.println(set2);
    

    Java系列(40)——集合(下)_数组_07

五、可变参数
  1. J2SE 1.5 以后的版本中提供了 Varargs 机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递多个可变的实参。

  2. 可变参数的语法

    修饰符 返回值类型 方法名(数据类型…变量)
    { 
    }
    
    public class DymanicParam
    {
    	public static void main(String[] args)
    	{
    		int[] p = { 1, 2, 3, 4, 5 };
    		int sum = add(p);
    		System.out.println(sum);
    	}
    
    	public static int add(int a, int b)
    	{
    		return a + b;
    	}
    
    	public static int add(int a, int b, int c)
    	{
    		return a + b + c;
    	}
    
    	/**
    	 * 可变参数的定义
    	 * 
    	 * int ... p 参数是一个int类型的数组,相当于int[] p
    	 */
    
    	public static int add(int... p)
    	{
    		int sum = 0;
    		for (int i = 0; i < p.length; i++)
    		{
    			sum += p[i];
    		}
    		return sum;
    	}
    }
    

    Java系列(40)——集合(下)_ide_08

六、Arrays 工具类
  1. 数组的工具类,这里的方法都是静态的。
    Java系列(40)——集合(下)_集合_09

  2. toString 方法Java系列(40)——集合(下)_java_10

  3. 把数组转换成字符串

    // int 类型数组
    int[] arr = { 12, 123, 55, 6 };
    System.out.println(Arrays.toString(arr));
    // 对象数组
    Student[] parr = { new Student(1, "张三", 23), new Student(1, "李四", 23) };
    System.out.println(Arrays.toString(parr));
    

    Java系列(40)——集合(下)_数组_11

  4. 对任意数组排序。
    (1)对 int 的数组做排序

    // 对 int 的数组做排序
    int[] arr = { 12, 123, 55, 6 };
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
    

    Java系列(40)——集合(下)_字符串_12
    (2)对索引1到索引4进行排序

    int[] arr = { 12, 123, 55, 6 };		
    // 对索引1到索引4进行排序
    Arrays.sort(arr, 1, 4);
    System.out.println(Arrays.toString(arr));
    

    Java系列(40)——集合(下)_集合_13
    Java系列(40)——集合(下)_java_14
    (3)对象排序

    Student[] parr = { new Student(2, "张三", 23), new Student(1, "李四", 23) };		
    System.out.println(Arrays.toString(parr));
    //排序规则是按照我们在Student类中所写的方法进行排序
    Arrays.sort(parr);
    System.out.println(Arrays.toString(parr));
    

    Java系列(40)——集合(下)_集合_15

  5. 对任意的数组做二分法的查找。

    // 二分法的查找是必须有序的数组,所以需要先做排序
    int[] arr = { 6, 12, 123, 555, 666 };
    //二分法查找元素555,返回索引
    System.out.println(Arrays.binarySearch(arr, 555));
    

    Java系列(40)——集合(下)_数组_16

  6. 把数组转换成List

    // 定义一个数组
    Integer[] arr = { 6, 12, 123, 555, 666 };
    // 把数组转换成list
    List<Integer> iList = Arrays.asList(arr);
    System.out.println(iList);
    // 从数组转换过来的list不能添加和删除,修改可以
    // iList.add(34);
    // iList.remove(1);
    iList.set(2, 345);
    System.out.println(iList);
    

    Java系列(40)——集合(下)_字符串_17
    注意
    Java系列(40)——集合(下)_数组_18

七、集合工具类

Java系列(40)——集合(下)_字符串_19

  1. 示例源码

    package cn.tx.set;
    
    public class Emp
    {
    	private int id;
    	private int age;
    
    	public Emp(int id, int age)
    	{
    		super();
    		this.id = id;
    		this.age = age;
    	}
    
    	public int getId()
    	{
    		return id;
    	}
    
    	public void setId(int id)
    	{
    		this.id = id;
    	}
    
    	public int getAge()
    	{
    		return age;
    	}
    
    	public void setAge(int age)
    	{
    		this.age = age;
    	}
    
    	@Override
    	public String toString()
    	{
    		return "Emp [id=" + id + ", age=" + age + "]";
    	}
    }
    
    package cn.tx.set;
    
    import java.util.Comparator;
    
    public class EmpComparator implements Comparator<Emp>
    {
    	@Override
    	public int compare(Emp e1, Emp e2)
    	{
    		int val = e1.getId() - e2.getId();
    		if (val == 0)
    		{
    			val = e1.getAge() - e2.getAge();
    		}
    		return val;
    	}
    }
    
    List<String> list = new ArrayList<String>();
    list.add("张三");
    list.add("李四");
    list.add("王五");
    list.add("赵六");
    list.add("田七");
    // 集合的反转
    Collections.reverse(list);
    System.out.println(list);
    // 随机打乱集合
    Collections.shuffle(list);
    System.out.println(list);
    
    // 排序
    List<String> list1 = new ArrayList<String>();
    list1.add("asd");
    list1.add("er");
    list1.add("tw");
    list1.add("qt");
    list1.add("gh");
    Collections.sort(list1);
    System.out.println(list1);
    
    List<Student> list2 = new ArrayList<Student>();
    list2.add(new Student(1, "zhangsan", 45));
    list2.add(new Student(4, "lisi", 42));
    list2.add(new Student(1, "wangwu", 12));
    Collections.sort(list2);
    System.out.println(list2);
    
    // 把list变成同步的(线程安全的)
    Collections.synchronizedList(list);
    
    // 对Emp排序,使用外部的比较器来做排序
    List<Emp> empList = new ArrayList<Emp>();
    empList.add(new Emp(5, 23));
    empList.add(new Emp(1, 24));
    empList.add(new Emp(1, 14));
    
    Collections.sort(empList, new EmpComparator());
    System.out.println(empList);
    

    Java系列(40)——集合(下)_字符串_20

  2. 面试题
    问:Collection 和 Collections 的区别?
    答:前者是集合的接口;后者操作集合的工具类。

如有错误,欢迎指正!