本系列博客汇总在这里:Java系列_汇总
目录
- 一、Set 集合(接口)
- 二、Set 集合的实现类 HashSet
- 1、HashSet 集合的特点
- 2、HashSet 是如何判断元素重复的
- 三、Set 集合的实现类 LinkedHashSet
- LinkedHashSet 特点
- 四、Set 集合的实现类 TreeSet
- 1、TreeSet 特点
- 2、自定义排序
- 五、可变参数
- 六、Arrays 工具类
- 七、集合工具类
一、Set 集合(接口)
二、Set 集合的实现类 HashSet
- HashSet 实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变,此类允许使用 null 元素。
- List 允许重复以及存在空值(可以多个)的。
1、HashSet 集合的特点
- 无序性 (跟添加的顺序无关);
- 不能重复 ;
- 允许有 null,但是只能有一个;
- HashSet 不是线程安全的。
2、HashSet 是如何判断元素重复的
- Set 在添加元素的时候会拿这个元素和集合中的每一个元素做比较,如果重复了就不添加,如果没有重复就添加。
- 在判断字符串是否重复的时候,是调用了 String 类里面的 equals() 方法;另外,判断两个对象是否相等,必须要重写 equals 和 hashCode 方法,这两个方法都符合相等的条件才认为是相等的两个对象,如下:
- 重写 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方法
public String toString()
{
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
/**
* 重写equal方法
*/
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
*/
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);
三、Set 集合的实现类 LinkedHashSet
- LinkedHashSet 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
- LinkedHashSet 的方法几乎都是继承于 HashSet,不同在于 LinkedHashSet 是有序的。
LinkedHashSet 特点
- 有序性(添加顺序);
- 不能重复;
- 允许有null,但是只能有一个;
- 不是同步的(不是线程安全的,效率高)。
四、Set 集合的实现类 TreeSet
TreeSet 可以支持自定义排序,如果 TreeSet 所存储的对象的类没有实现 Comparable 接口就会抛出异常 ClassCastException,所以我们如果想要使用TreeSet来对自定义的对象来排序必须实现Comparable 接口。
1、TreeSet 特点
- 元素唯一性;
- 可自定义排序;
- 不允许 null 存在;
- 不是线程安全。
2、自定义排序
类必须要实现一个接口 Comparable 才能做排序,之前所介绍的集合之所以没有顺序,就是因为此原因。
Compare 比较两个字符串
String str = "nbc";
String str1 = "nbc";
// 返回一个int类型的数字
/*
说明:两个字符串相互比较,从第一个字符开始比较相同索引的字符,如果第一个字符串的第一个字符比第二个字符串的第一
个字符大(ASCII 码),就可以判断整个字符串比第二个字符串大;如果两个字符串的第一个字符相等,再去比较他们的第二个
字符,同样遵守上述规律。
*/
int val = str.compareTo(str1);
System.out.println(val);ASCII 表
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、如果学号和年龄都相等,就按照名字的字符来比较。
*/
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;
}
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大");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);
五、可变参数
J2SE 1.5 以后的版本中提供了 Varargs 机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递多个可变的实参。
可变参数的语法
修饰符 返回值类型 方法名(数据类型…变量)
{
}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;
}
}
六、Arrays 工具类
数组的工具类,这里的方法都是静态的。
toString 方法
把数组转换成字符串
// 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));对任意数组排序。
(1)对 int 的数组做排序// 对 int 的数组做排序
int[] arr = { 12, 123, 55, 6 };
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
(2)对索引1到索引4进行排序int[] arr = { 12, 123, 55, 6 };
// 对索引1到索引4进行排序
Arrays.sort(arr, 1, 4);
System.out.println(Arrays.toString(arr));
(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));对任意的数组做二分法的查找。
// 二分法的查找是必须有序的数组,所以需要先做排序
int[] arr = { 6, 12, 123, 555, 666 };
//二分法查找元素555,返回索引
System.out.println(Arrays.binarySearch(arr, 555));把数组转换成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);
注意
七、集合工具类
示例源码
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;
}
public String toString()
{
return "Emp [id=" + id + ", age=" + age + "]";
}
}package cn.tx.set;
import java.util.Comparator;
public class EmpComparator implements Comparator<Emp>
{
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);面试题
问:Collection 和 Collections 的区别?
答:前者是集合的接口;后者操作集合的工具类。
如有错误,欢迎指正!