集合嵌套之ArrayList嵌套ArrayList
eg.
自定义Person类,成员变量name,age私有,有参无参,get(),set(),覆写toString()
import java.util.ArrayList; import com.xxx.bean.Person; public class Demo3_ArrayLIstArrayList { /* * 集合嵌套之ArrayList嵌套ArrayList 有一个group: 分为两个小组 g1 和 g2 */ public static void main(String[] args) { ArrayList<ArrayList<Person>> group = new ArrayList<>(); ArrayList<Person> g1 = new ArrayList<>(); g1.add(new Person("李小璐", 32)); g1.add(new Person("马苏", 30)); g1.add(new Person("杨幂", 30)); ArrayList<Person> g2 = new ArrayList<>(); g2.add(new Person("贾乃亮", 32)); g2.add(new Person("孔令辉", 30)); g2.add(new Person("刘恺威", 30)); group.add(g1); group.add(g2); for (ArrayList<Person> g : group) { // 使用增强for循环嵌套增强for循环来遍历 for (Person p : g) { System.out.println(p); } System.out.println(); } } }
HashSet存储字符串和自定义对象并遍历
遍历:没有索引,不能用.size() getIndex()遍历;不能用普通for循环,普通for循环i代表索引;可以用增强for循环,因为Set体系是Collection子类,Collection里面有Iterator迭代器,而增强for循环底层依赖的是迭代器。(只要能用迭代器迭代的,就可以用增强for循环遍历)。
如何保证存储自定义对象保证元素唯一?
重写equals()方法,但是没有被调用,因为每次传入一个对象,会调用父类的hashCode(),
每个对象返回的hashcode值都不相同,所以都存进来了。因此,还要重写hashCode()方法,hashCode返回值是一个数,正数代表右边,负数代表左边,0不存。当hashcode值相等的时候,才会调用equals方法。
如何减少调用equals()方法,提高代码的运行效率。将hashCode返回值为变量。
最终版:用自带的,同时重写equals()和hasnCode() 快捷键alt+shift+s +h
eg
import java.util.HashSet; import com.xxx.bean.Person;//Person类省略 public class Demo1_HashSet { public static void main(String[] args) { //demo1(); HashSet<Person> hs = new HashSet<>(); hs.add(new Person("张三", 23)); hs.add(new Person("张三", 23)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); //System.out.println(hs.size()); System.out.println(hs); } private static void demo1() { HashSet<String> hs = new HashSet<>(); hs.add("c"); boolean b1 = hs.add("a"); boolean b2 = hs.add("a"); hs.add("b"); hs.add("d"); System.out.println(hs); // System.out.println(b1); // System.out.println(b2); for (String string : hs) { System.out.println(string); } } }
LinkedHashSet的概述和使用
LinkedHashSet是HashSet子类,底层哈希算法实现和链表结构实现。
特点:与HashSet相比,它可以存取有序。
day23
练习:
1. 编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。
分析:
1.随机数,创建随机数对象Random
2.创建一个set集合对象,可以自动去除重复
3.10个随机数 while,如果集合中的随机数不到10,就一直添加到集合
4.遍历集合,打印输出到控制台
import java.util.HashSet; import java.util.Random; public class Test1 { public static void main(String[] args) { // 1.随机数,创建随机数对象Random Random r = new Random(); // 2.创建一个set集合对象,可以自动去除重复 HashSet<Integer> hs = new HashSet<>(); // 3.10个随机数 while,如果集合中的随机数不到10,就一直添加到集合 while (hs.size() < 10) { System.out.println("添加前 size = " + hs.size()); int num = r.nextInt(20) + 1; hs.add(num); // 自动装箱 System.out.println("添加后 size = " + hs.size()); System.out.println(); } // 4.遍历集合,打印输出到控制台 for (Integer integer : hs) { System.out.println(integer); } } }
2. 使用Scanner从键盘读取一行输入,去掉其中重复字符, 打印出不同的那些字符
分析:
1.键盘录入Scanner
2.用String line 来接收键盘录入,将字符串转换成字符数组
3.去除重复,创建set集合,将数组中的每一个字符存储到set集合中,自动去除重复
4.遍历集合,输出打印
eg.
import java.util.HashSet; import java.util.Scanner; public class Test2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串:"); String line = sc.nextLine(); char[] arr = line.toCharArray(); HashSet<Character> hs = new HashSet<>(); for(char c: arr) { hs.add(c); } for(Character ch : hs) { System.out.print(ch); } } }
3. 将集合中的重复元素去掉
分析:
1.定义一个list集合,存储重复的元素
2.定义一个方法,去除集合中的重复元素
3.输出打印list集合
eg.
import java.util.ArrayList; import java.util.HashSet; import java.util.List; public class Test3 { public static void main(String[] args) { // 1.定义一个list集合,存储重复的元素 ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("b"); list.add("b"); list.add("c"); list.add("c"); list.add("c"); list.add("c"); System.out.println(list); //没去重 //2.定义一个方法,去除集合中的重复元素 getSingle(list); //3.输出打印list集合 System.out.println(list); //去重 } /* * 去除集合中的重复元素 * 1.void * 2.List<String> list * * 分析: * 1.去除重复:创建一个set集合 * 2.将list集合中的所有元素添加到set集合中,自动去除重复 * 3.将list集合清空 * 4.将set集合中的所有元素添回到list */ public static void getSingle(List<String> list) { HashSet<String> hs = new HashSet<>(); hs.addAll(list); //去除重复 list.clear(); list.addAll(hs); } }
在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复
分析:
1.定义list集合存储无序并重复的字符串
2.定义一个方法,让其有序并保留重复
3.遍历list集合
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.TreeSet; public class Test4 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("ccc"); list.add("ccc"); list.add("aaa"); list.add("aaa"); list.add("zuikc"); list.add("bbb"); list.add("bbb"); list.add("fff"); list.add("aaa"); //2.定义一个方法,让其有序并保留重复 sort(list); //3.遍历list集合 System.out.println(list); } /* * 定义一个方法,让其有序并保留重复 * 1.返回值类型 void * 2.参数列表 List<String> list * * 1.要排序,创建TreeSet集合对象,传入比较器(按照比较器排序) * 2.将list集合中的所有元素添加到TreeSet集合 * 3.将list集合清空 * 4.将set集合中保留重复有序的元素添回到list集合 */ public static void sort(List<String> list) { //1.要排序,创建TreeSet集合对象,传入比较器(按照比较器排序) TreeSet<String> ts = new TreeSet<>(new Comparator<String>() { @Override public int compare(String s1, String s2) { int num = s1.compareTo(s2); //首要条件比较的是内容 return num == 0 ? 1 : num; //保留重复:只要返回值变成非0数字即可 } }); //2.将list集合中的所有元素添加到TreeSet集合 ts.addAll(list); //3.将list集合清空 list.clear(); //4.将set集合中保留重复有序的元素添回到list集合 list.addAll(ts); } }
TreeSet
TreeSet存储Integer类型的元素并遍历
TreeSet是用来对元素进行排序的(自然排序),同样也可以保证元素的唯一
如果compareTo()方法的返回值是0,集合中只有一个元素
如果compareTo()方法的返回值是正数,集合中的元素怎么存,就怎么取(正序排序)
如果compareTo()方法的返回值是负数,集合中的元素倒序排序
自然顺序(Comparable)
TreeSet类的add()方法中会把存入的对象提升为Comparable类型
调用对象的compareTo()方法和集合中的对象比较
根据compareTo()方法返回的结果进行存储
Person类implements Comparable 重写compareTo()
import java.util.TreeSet; import com.xxxx.bean.Person; public class Demo1_TreeSet { public static void main(String[] args) { //demo1(); //demo2(); //按照姓名的长度排序 TreeSet<Person> ts = new TreeSet<>(); ts.add(new Person("zhangsan", 23)); ts.add(new Person("lisi", 13)); ts.add(new Person("wangwu", 43)); ts.add(new Person("aaaa", 53)); ts.add(new Person("aaaa", 63)); ts.add(new Person("zhaoliu", 33)); System.out.println(ts); } private static void demo2() { TreeSet<Person> ts = new TreeSet<>(); ts.add(new Person("李四", 13)); ts.add(new Person("张三", 23)); ts.add(new Person("张三", 3)); // ts.add(new Person("周七", 13)); ts.add(new Person("王五", 43)); ts.add(new Person("赵六", 33)); System.out.println('张' + 0); //unicode值 System.out.println('李' + 0); System.out.println('王' + 0); System.out.println('赵' + 0); System.out.println(ts); } private static void demo1() { TreeSet<Integer> ts = new TreeSet<>(); ts.add(3); ts.add(1); //自动装箱 ts.add(1); ts.add(2); ts.add(2); System.out.println(ts); } } 重写的compareTo @Override //姓名的长度是首要条件 --> 姓名内容 ---> 年龄 public int compareTo(Person o) { int length = this.name.length() - o.name.length(); //姓名的长度是首要条件 int num = length == 0 ? this.name.compareTo(o.name) : length; //姓名的内容是次要条件 return num == 0 ? this.age - o.age : num; //年龄是次次要条件 } /*//比较姓名 @Override public int compareTo(Person o) { int num = this.name.compareTo(o.name); //姓名是比较的主要条件 return num == 0 ? this.age - o.age : num; //年龄是比较的次要条件 }*/ /*@Override //比较年龄 public int compareTo(Person o) { int num = this.age - o.age; //年龄是比较的主要条件 return num == 0 ? this.name.compareTo(o.name) : num ; //姓名是比较的次要条件 }*/
比较器顺序(Comparator)
创建TreeSet的时候可以制定一个Comparator
如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
add()方法内部会自动调用Comparator接口中compare()方法排序
调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
import java.util.Comparator; import java.util.TreeSet; public class Demo2_TreeSet { /* * TreeSet保证元素唯一和比较器排序的原理及代码实现 * 需求:将字符串按照长度排序 * * 比较器排序优先于自然排序 */ public static void main(String[] args) { TreeSet<String> ts = new TreeSet<>(new CompareByLen()); //传入比较器 Comparator c = new CompareByLen(); ts.add("aaaaaaaaaaaaa"); //父类引用指向子类对象:多态 ts.add("z"); ts.add("wc"); ts.add("nba"); ts.add("cba"); System.out.println(ts); } } 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; //内容是比较的次要条件 } }
两种方式的区别
TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
TreeSet如果传入Comparator, 就优先按照Comparator进行排序
在集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复。
分析:
1.定义list集合存储无序并重复的字符串。
2.定义一个方法,让其有序并保留重复。
3.遍历list集合
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.TreeSet; public class Test4 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("ccc"); list.add("ccc"); list.add("aaa"); list.add("aaa"); list.add("zuikc"); list.add("bbb"); list.add("bbb"); list.add("fff"); list.add("aaa"); //2.定义一个方法,让其有序并保留重复 sort(list); //3.遍历list集合 System.out.println(list); } /* * 定义一个方法,让其有序并保留重复 * 1.返回值类型 void * 2.参数列表 List<String> list * * 1.要排序,创建TreeSet集合对象,传入比较器(按照比较器排序) * 2.将list集合中的所有元素添加到TreeSet集合 * 3.将list集合清空 * 4.将set集合中保留重复有序的元素添回到list集合 */ public static void sort(List<String> list) { //1.要排序,创建TreeSet集合对象,传入比较器(按照比较器排序),匿名内部类 TreeSet<String> ts = new TreeSet<>(new Comparator<String>() { @Override public int compare(String s1, String s2) { int num = s1.compareTo(s2); //首要条件比较的是内容 return num == 0 ? 1 : num; //保留重复:只要返回值变成非0数字即可 } }); //2.将list集合中的所有元素添加到TreeSet集合 ts.addAll(list); //3.将list集合清空 list.clear(); //4.将set集合中保留重复有序的元素添回到list集合 list.addAll(ts); } }
从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloworld 程序打印:dehllloorw
分析:
1.键盘录入Scanner
2.要排序,创建TreeSet集合,又因为保留了重复的字符,传入比较器
3.用line接收键盘录入的字符串,将line转换成字符数组,获取每一个字符
4.遍历数组,将每一个字符存储到set集合中
5.遍历set集合,打印输出每一个字符
import java.util.Comparator; import java.util.Scanner; import java.util.TreeSet; public class Test5 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串"); TreeSet<Character> ts = new TreeSet<>(new Comparator<Character>() { @Override public int compare(Character c1, Character c2) { int num = c1.compareTo(c2); //两者功能一样 // int num = c1 - c2; return num == 0 ? 1 : num; } }); String line = sc.nextLine(); char[] arr = line.toCharArray(); for (char c : arr) { ts.add(c); //自动装箱 } for(Character ch : ts) { System.out.print(ch); } } }
程序启动后, 可以从键盘输入接收多个整数, 直到输入quit时结束输入. 把所有输入的整数倒序排列打印.
分析:
1.键盘录入Scanner
2.排序,所以要创建TreeSet集合对象,又因为是倒序排序,传入比较器(按照倒序排序)
3.接收多个整数,要用循环(无限循环);
4.在循环中做判断:如果接收的是字符串quit,终止循环break;如果是数字字符串,将该字符串转换Integer存在set集合中
5.遍历set集合,输出打印每一个int数
import java.util.Comparator; import java.util.Scanner; import java.util.TreeSet; public class Test6 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入数据:"); TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() { @Override public int compare(Integer i1, Integer i2) { //int num = i2 - i1; int num = i2.compareTo(i1); return num == 0 ? 1 : num; } }); while(true) { //因为要录入不确定的个数,所以用无线循环 String line = sc.nextLine(); if("quit".equals(line)) { break; } Integer i = Integer.parseInt(line); //将数字字符串转换成int数 ts.add(i); } for (Integer integer : ts) { System.out.println(integer); } } }
迭代总结
1.List
a.普通for循环, 使用get(int index)逐个获取 (Set没有,因为没有索引)
b.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
c.增强for循环, 只要可以使用Iterator的类都可以用
d.Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法
2.Set
a.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
b.增强for循环, 只要可以使用Iterator的类都可以用
3.普通for循环,迭代器,增强for循环不能在遍历的过程中删除
/*
* 去除集合中的重复元素
* 1.void
* 2.List<String> list
*
* 分析:
* 1.去除重复:创建一个set集合
* 2.将list集合中的所有元素添加到set集合中,自动去除重复
* 3.将list集合清空
* 4.将set集合中的所有元素添回到list
*/
publicstaticvoid getSingle(List<String> list) {
HashSet<String> hs = new HashSet<>();
hs.addAll(list); //去除重复
list.clear();
list.addAll(hs);
}
}