java容器练习

Java容器相关练习,最后是知识总结

一基本方法练习,

通过练习ArrayList熟悉容器操作

复制代码
  1 package org;
  2 
  3 import java.util.*;
  4 //前言:
  5 /*
  6 *
  7 * 关系树
  8 * Iterable->map<K,value>/Collection<? extends E>
  9 * Collection<? extends E>  -> list/set
 10 * List-> ArrayList
 11 * set->hashset
 12 *
 13 * */
 14 //List容器练习
 15 //1、初始化 1、<>告诉它是什么类型。
 16 //2、添加 1、add()追加,add(index,value)某一位置插入2、addAll(Collection< extends E>)
 17 //3、删除 1、remove(index),remove(Obj) ,removeAll(Collection< extends E>) ,clear()
 18 //4、修改 1、set(index,value)
 19 //5、遍历 1、for>for in(没啥)  , iterator (hasnext()) .next()
 20 //6、长度(元素个数),转换 1、换为数组, 建立数组(size()) toArray([])  2、数组变为容器,new ArrayList(Array.asList([]));
 21 //7、排序*** sort(CompareTo) Collections.shuffle(list);
 22 //8、查找*** indexof(Obj) lastindexof(Obj)
 23 //9、是否存在 contains(Obj) containsAll(Collection) 是否为空 isEmpty()
 24 //10、截取 subList(from,to)  [from,to)
 25 //11、保留 retainAll retain()  保留里面的,
 26 //12、迭代器 Iterator   hasNext  next()
 27 //13、List.of 返回一个 ArrayList()容器实现类,这个ArrayList是不能增加,删除 类似Array.asList()
 28 
 29 //总结:
 30 /*
 31 *
 32 * 1、ArrayList是一个工具
 33 *   1、泛型,存放Object类元素,基本数据类型就不要存放了
 34 *   2、相比较于数据可以批量操作,长度是可变的,所以好的利用效率很高,尽量不要一个一个的操作。
 35 *   3、可以通过迭代器遍历,也可随机存取
 36 *
 37 *
 38 *
 39 * */
 40 
 41 public class Test {
 42     public static void testlist(){
 43         //几个容器的关系 --接口,接口,实现类
 44         //Iterable<T> --- Collection<E>  -- List<E> set<E>  ArrayList<E>  Has
 45         //        List
 46         //我知道我的实现类实现了我的方法,利用重载机制就行了。所以可以通过实例化实现类,来对接口赋值,
 47         //我的方法就是我的实现类的方法,还有我的实现类没有重载的,但是我实现的方法。
 48         List<String> list = new ArrayList<String>();
 49         //list<E>,的E最好给一个类型,否则只能用公共的方法,公共的就是父类定义的。还要受到权限影响。
 50         Set set = new HashSet();
 51         //E里面都是类,不是基本数据类型、
 52         Map<Integer,String> map = new HashMap<Integer, String>();
 53         list.add("张三");
 54         list.add("李四");
 55         list.add("王五");
 56         list.add("赵六");
 57         list.add("张四");
 58 
 59         System.out.println(list.toString());
 60         set.add(list);//参数类型是list,个数还是一个
 61         System.out.println(set);
 62         System.out.println(list.get(0) instanceof String ? true : false);
 63         System.out.println("添加一群元素到集合中,一定效率高于一个一个添加");
 64         list.addAll(List.of("java","html","c/c++","servlet","mysql"));
 65         System.out.println("容器是否有某个元素"+list.contains("mysql"));
 66         System.out.println("容器是否有某些元素,需要用到容器"+list.containsAll(List.of("java", "html")));
 67 
 68 
 69         //输出
 70         for (String s : list) {
 71             System.out.println(s+" ");
 72         }
 73         System.out.println();
 74         for(int i = 0;i<list.size();i++){
 75             System.out.print(list.get(i)+" ");
 76         }
 77         //从后往前遍历容器
 78         for (int i= list.size()-1;i>=0;i--){
 79             System.out.print(list.get(i)+" ");
 80         }
 81         //查找某一个元素
 82         System.out.print("java的下标是:");
 83         System.out.print(list.indexOf("java"));
 84         System.out.print(" ");
 85         System.out.print(list.lastIndexOf("java"));
 86         //得到某个位置的元素
 87         System.out.println("下标为1的元素是:"+list.get(1));
 88         //在某个位置插入元素
 89         list.add(1,"mysql");
 90         //清空所有元素
 91         list.clear();
 92         //判断容器是否为空
 93         System.out.println(list.isEmpty());
 94 
 95 
 96     }
 97     public static void testList2(){
 98         //容器和字符串之间的转换
 99         //字符串数组
100         List<String> list = new ArrayList<String>();
101         list.addAll(List.of("赵云","关羽","诸葛亮","曹操","周瑜"));
102         String[] strs = new String[list.size()];
103         list.toArray(strs);
104         //通过Arrays工具输出字符串数组.
105         System.out.println(Arrays.toString(strs));
106 
107         //字符串数组变为ArrayList
108         //同样是利用Arrays  000000000 数组工具类
109         List<String> myList = Arrays.asList(strs);//数组变为ArrayList之后,容器就不能增加,删除。
110         System.out.println(myList);
111         //参数是一个方法(接口),作用是比较两个数的大小,如果前面的值大,返回值是正数,
112         //方法一改,如果前面大,返回值是负数,那么结果就是从小到大排序了。  里面是排序算法
113         //这里元素就是String类型,泛型的原因
114         //返回值是一个int类型
115 
116         myList.sort((a,b)-> a.compareTo(b));
117         System.out.println("正序排序后"+myList);
118         //添加一个负号
119         myList.sort((a,b)->-a.compareTo(b));
120         System.out.println("倒序排序后"+myList);
121         //这是idea给我的方法
122         myList.sort(String::compareTo);
123         System.out.println("正序排序后"+myList);
124         //有点像Array里面的sort方法
125 
126         //截取容器
127         //List<E> subList(int fromIndex, int toIndex);
128 
129         // 下表范围 [2,3)
130         myList.subList(2,3);
131 //        System.out.println(myList);//并没有改变原来的容器
132         System.out.println(myList.subList(2,3));
133         //截取之后的元素
134         System.out.println(myList.subList(myList.indexOf("诸葛亮"), myList.size()-1));
135 
136         //截取元素并不能从一个位置截到最后一个位置,
137 //        String.substring()//String里面有两个方法。
138 //        System.out.println(myList.subList(myList.indexOf("诸葛亮")));
139 
140         //看看一群元素是否都有,不考虑位置
141         System.out.println(myList.containsAll(List.of("诸葛亮","赵云")));
142         //不允许删除,添加
143 //        myList.add("张三");
144         myList.set(0,"王五");
145         System.out.println(myList);
146 //        myList.remove(0);
147         //        System.out.println(myList.retainAll(List.of("关羽")));//保留
148 
149 
150     }
151     //再次验证一下integer数组
152     public static void testList4(){
153         //将int[]转为integer[]
154         List<Integer> myList = new ArrayList();
155         int[] arr = new int[]{1,2,3,4,5,6,7,8,34,2,1};
156         Integers integers = new Integers(arr);
157         myList.addAll(Arrays.asList(integers.toIntegers()));
158         myList.sort((a,b)->a-b);
159         System.out.println(myList);
160         myList.sort((a,b)->b-a);
161         System.out.println(myList);
162         //add不同于赋值
163         myList.add(10);
164         myList.remove(0);
165     }
166 
167     public static void testList5(){
168         int[] arr = new int[]{1,2,3,4,5,6,7,8,34,2,1};
169         Integers integers = new Integers(arr);
170         List<Integer> myList = Arrays.asList(integers.toIntegers());
171         myList.sort((a,b)->a-b);
172         System.out.println(myList);
173         myList.sort((a,b)->b-a);
174         System.out.println(myList);
175         //add不同于赋值
176         try {
177            myList.add(10);
178         }catch (UnsupportedOperationException e){
179             System.out.println("不可以添加");
180         }
181         catch (Exception e){
182             System.out.println("未知异常添加失败");
183         }
184 
185         try{
186             myList.remove(0);
187         }
188         catch (Exception e){
189             System.out.println("不能删除第1个元素");
190         }
191     }
192 
193 
194     //迭代器练习
195     /*
196     *
197     * 泛型
198     * 1、类型必须是类
199     * 2、尽量告诉一下,
200     * 3、类型不匹配异常是常有的, java.lang.ClassCastException。
201     *       1、迭代器
202     *       2、add,添加
203     *
204     *
205     * */
206 
207     public static void  testList3(){
208         List myList = new ArrayList<>();
209         try {
210             myList.addAll(List.of(1,3,4,"张四",6,1.12,"李四","赵四"));
211         }
212         catch (UnsupportedOperationException e){
213             System.out.println("多种类型,类型不匹配");
214         }
215         //迭代器只读吗?,可以修改,添加,删除
216         //Iterator 类型可以设置一下,防止意外.
217         Iterator<Object> it = myList.iterator();
218         System.out.println("第4个元素的类型是Integer吗"+ (myList.get(3) instanceof Integer));
219         int count = 0;
220         while(it.hasNext()){
221             count++;
222             try {
223                 //迭代器不能输出Integer,Double,因为我没有设,默认了
224                 System.out.println(it.next().toString());
225             }
226             catch (ClassCastException e){
227                 //利用try catch可以看看那个元素出问题。
228                 System.out.printf("第%d个元素出现问题",count);
229             }
230         }
231 
232     }
233 
234 
235     public static void main(String[] args){
236         testList3();
237     }
238 }
239 
240 //对象排序
241 class User{}
242 
243 //汉字排序
244 //对象排序, compareTo
复制代码

二HashSet练习总结

复制代码
  1 package cn;
  2 
  3 
  4 import java.util.*;
  5 
  6 //集合是新的空间--存放的值是地址
  7 //存储器保证值唯一
  8 //链表,不能随机访问
  9 
 10 public class Test {
 11     {
 12         coder = 19;//可以设置成一个常量值。
 13     }
 14 
 15     Void a = null;//Void类,
 16     private final byte coder;
 17 
 18 
 19     public Test() {
 20         //可以在构造函数中初始化coder
 21 //        coder = 0;
 22     }
 23     //String//包装类
 24 
 25     //set练习:
 26     //1、增加,添加一群 add addAll
 27     //2、删除,删除一群
 28     //3、修改,不可直接修改,但是添加时可以覆盖。
 29     //4、查找,只能遍历,不能随机查找
 30     //5、排序,不存在
 31     //6、是否包含
 32     public static void test1() {
 33         Set<String> set = new HashSet<String>();
 34         //测试一 添加
 35         // 1、hashset里面是有顺序的,不管你按什么怎么添加,它始终在那个位置. 和添加顺序无关。
 36         String[] strArr = new String[]{"诸葛亮", "汉武帝", "秦始皇", "汉高帝"};
 37         set.addAll(Arrays.asList(strArr));
 38         set.addAll(Set.of("张三", "李四", "王五", "赵六"));
 39         for (String string : set) {
 40 //            System.out.print(string);
 41         }
 42         System.out.println();
 43         //使用迭代器,自动递增
 44         Iterator<String> iterator = set.iterator();
 45         while (iterator.hasNext()) {
 46             System.out.println(iterator.next());
 47         }
 48 
 49 
 50         //2、每个值只存一次,String字符串,包装类是特殊的,他们并不是通过==比较值,而是通过equals比较
 51         //存的是一个地址,(字符串,new区别很大)
 52 //        System.out.println(set.size());
 53         String a = new String("刘高源");
 54         String b = new String("刘高源");
 55 
 56         set.add(a);
 57         set.add(b);//第二次就不存了,可以通过地址探究,遍历最后的值就是地址
 58         System.out.println(set.size());
 59         a = b;
 60 //        b = "李四";//b又出现了,,可以看出字符串常量内存中只有一份。
 61         b = new String("李四");//字符数组,
 62         System.out.println("----------------------------------------");
 63         System.out.printf("a的值是%s%n", a);
 64         iterator = set.iterator();
 65         //不能直接比较迭代器
 66         while (iterator.hasNext()) {
 67             String temp = iterator.next();
 68             System.out.println(temp);
 69             if (a == temp) {
 70                 System.out.println("a的地址存入了");
 71             }
 72             if (b == temp) {
 73                 System.out.println("b的地址存入了");
 74             }
 75 //            if(b==iterator.next()){
 76 //                System.out.println("b的地址存入了");
 77 //            }//越界了
 78         }
 79 
 80         //for in 效率很慢
 81         for (String str : set) {
 82             if (str == a) {
 83                 System.out.println("a的地址存入了");
 84             }
 85             if (str == b) {
 86                 System.out.println("b的地址存入了");
 87             }
 88         }
 89 
 90         System.out.println("添加前set长度是:" + set.size());
 91         System.out.println("添加Integer后set长度是:" + set.size());
 92         System.out.println("添加User后set长度是:" + set.size());
 93     }
 94 
 95     //Integer包装类
 96     //自动装箱,自动拆箱
 97     public static void testIntegerSet() {
 98         Set<Integer> set = new HashSet<Integer>();
 99         set.addAll(Set.of(1, 2, 3, 4, 5, 6, 7, 9, 32, 12, 67, 34, 54, 23, 31));
100 
101 
102         set.add(20);
103         System.out.println("添加前set长度是:" + set.size());//长度是16
104         set.add(20);
105         System.out.println("添加Integer后set长度是:" + set.size());//长度是16
106 
107         //自动包装了,其实和add20一样
108         set.add(new Integer(20));
109         System.out.println("添加Integer后set长度是:" + set.size());//长度是16
110         //自动装箱案例
111         Integer a = 1;//相当于重新new了一个
112         Integer b = a;//共用地址
113         b = 10;//重新new了,地址就变了
114         System.out.printf("a的值是%d", a);//1
115 
116         //1、说明了set会包装类保证值不重复。不管地址是否一样,只要值一样认为是一个。
117         //2、自动装箱练习。
118     }
119 
120     public static void testStringSet() {
121         Set<String> set = new HashSet();
122         set.add("张三");
123         System.out.printf("添加字符串前set容器长度是%d", set.size());//1
124         set.add("张三");
125 
126         set.add(new String("张三"));
127         System.out.printf("添加字符串后set容器长度是%d", set.size());//1
128         //字符串类似包装类,这里也是按照那个原则。
129         //字符串""也是可看成字符串,类似自动装箱。
130     }
131 
132 
133     public static void testUserSet() {
134         Set<User> set = new HashSet<User>();
135         set.addAll(Set.of(new User(), new User(), new User(), new User(), new User()));
136         System.out.printf("添加前set长度是:%d\n", set.size());//5
137         User u = new User();
138         set.add(u);
139         set.add(u);
140         System.out.printf("添加User后set长度是:%d%n", set.size());//6
141 
142         //自定义类,普通的类并不会比较值,Comparable<User>接口,equals方法重写了也不行。
143         //set认为只要地址不同就是不同的,地址相同就是同一个,
144     }
145 
146 
147     //探究字符数组和通过字符数组new出来的字符串之间关系
148     //String是通过一个新的byte数组存储的,还有一些其它标志
149     /*
150      * 分配一个新的 String,
151      * 以便它表示当前包含在字符数组参数中的字符序列。
152      * 复制字符数组的内容;
153      * 对字符数组的后续修改不会影响新创建的字符串。
154      * */
155 
156     public static void testCharArr() {
157 
158         char[] temp = new char[]{'刘', '高', '源'};
159         String str1 = new String(temp);
160         String str2 = new String(temp);
161         temp[0] = '中';
162         System.out.println(str1);
163         //字符串并不和字符数组共用地址(也就是不能赋值)。也是,他们毕竟不是同一个类型。
164         System.out.println(str1 == str2 ? true : false);
165 //        System.out.println("" instanceof String);//""引起来的字符串常量也是字符串。
166     }
167 
168     //hashset的删除,修改,查找
169     public static void test2() {
170         //1、删除remove,removeAll
171         HashSet<String> set = new HashSet();
172         //删除值为张三的元素
173         System.out.println(set.remove("张三"));//false
174         set.add("张三");
175 //        set.add("李四");
176 //        set.add("王五");
177         //批量删除所有值为张三,李四,王五的元素
178         //删除一个就返回true
179         System.out.println(set.removeAll(List.of("张三", "李四", "王五")));
180 
181         //清空所有元素
182         set.clear();
183         //2修改,没有找到  --- 不能修改
184 //        set.
185 
186         //3查找,没有找到方法
187 
188 //        System.out.println(set.getClass());
189     }
190 
191     //迭代器
192     //迭代器的遍历---使用迭代器遍历HashSet容器,hasNext() next()
193     //迭代器的删除---使用迭代器删除HashSet容器元素 remove()
194     //没有迭代器的修改
195 
196     public static void test3() {
197         HashSet<String> set = new HashSet();
198         set.addAll(List.of("卫青","霍去病","汉武帝","张骞"));
199         Iterator<String> it = set.iterator();
200         String temp ;
201         while(it.hasNext()){
202 //            //通过迭代器删除值为“汉武帝”的元素
203             //易错点:原因是:一次循环,应该是一次指针后移
204             //这样不仅判断的元素少了,输出的元素也少了
205 //            if("汉武帝".equals(it.next())){
206 //                it.remove();
207 //                continue;
208 //            }
209 //            System.out.print(it.next());
210             temp = it.next();
211             if("汉武帝".equals(temp)){
212                 it.remove();
213                 continue;
214             }
215             System.out.println(temp);
216         }
217         //HashSet.toString();
218         System.out.println(set);
219     }
220 
221     //补充  List用迭代器删除元素
222 
223     public static void testIterator(){
224         ArrayList<String> list1 = new ArrayList();
225         LinkedList<String> list2 = new LinkedList();
226         list1.addAll(List.of("卫青","霍去病","汉武帝","张骞"));
227         list2.addAll(List.of("卫青","霍去病","汉武帝","张骞"));
228         Iterator<String> it = list1.iterator();
229         String temp;
230         while(it.hasNext()){
231             temp = it.next();
232             if("汉武帝".equals(temp)){
233                 it.remove();
234                 continue;
235             }
236             System.out.println(temp);
237         }
238         System.out.println("-----------------------------");
239         it = list2.iterator();
240         while(it.hasNext()){
241             temp = it.next();
242             if("汉武帝".equals(temp)){
243                 it.remove();
244                 continue;
245             }
246             System.out.println(temp);
247         }
248     }
249 
250     public static void test4(){
251 
252         List<String> list = List.of("卫青","霍去病","汉武帝","张骞");
253 //        list.remove(0);
254 // 不能删除;原因是相当于 List.of("卫青","霍去病","汉武帝","张骞").remove()
255         Iterator<String> it = list.iterator();
256 //        while(it.hasNext()){
257 //            it.next();
258 //            it.remove();
259 //        }
260 //      //也不能用迭代器删除,迭代器根据对象来的
261 
262         list = Arrays.asList(new String[]{"卫青","霍去病","汉武帝","张骞"});
263 //        list.remove(0);
264 // 相当于 Arrays.asList(new String[]{"卫青","霍去病","汉武帝","张骞"}.remove()
265         it = list.iterator();
266 //        while(it.hasNext()){
267 //            it.next();
268 //            it.remove();
269 //        }
270         //不能删除
271 
272         //解决办法,拷贝值,类似字符串处理字符数组
273 
274         list = null;
275         list.addAll(List.of("卫青","霍去病","汉武帝","张骞"));
276         list.remove(0);
277         list.addAll(Arrays.asList(new String[]{"卫青","霍去病","汉武帝","张骞"}));
278         it = list.iterator();
279         while(it.hasNext()){
280             it.next();
281             it.remove();
282         }
283 
284         //总结:
285         //1、容器是一个独立的存储空间,起到存储元素的作用;
286         //2、容器操作可以是容器整体的操作,如addAll,removeAll;也可以是元素的操作,添加,查看(set不可以),删除,修改(set不可以),
287         //3、添加是拷贝值
288         //4、赋值是共用地址
289         //5、迭代器可以实现遍历修改,操作
290 
291     }
292 
293     //总结,只要容器是可变的的,那么就能删除,也就能用迭代器删除。
294     //即容器可以按照可变长,不可变长分类。
295 
296     //HashSet其它操作
297     public static void test5(){
298         HashSet<Integer> set = new HashSet<>();
299         //包含元素AAA吗?
300         System.out.println(set.contains(1));
301 
302         //包含一批元素(容器AAA)吗?
303         System.out.println(set.containsAll(List.of("汉武帝", "卫青")));
304 
305         //容器是空的吗?
306         System.out.println(set.isEmpty());
307 
308         set.addAll(List.of(1,2,3,4,5));
309 
310         //克隆给数组的操作,
311         //问题是,是共用地址,还是在数组原有的里面修改。
312         Integer[] test = new Integer[set.size()];//分配合适空间
313         Integer[] copy = set.toArray(test);
314         System.out.println(Arrays.toString(test));
315         test[2] = 6666;
316         System.out.println(Arrays.toString(test));
317         System.out.println(set);//发现是克隆
318         System.out.println(copy==test);//true 返回数组就是实际参数
319 
320         //那么如果空间不够,或者空间更多什么结果
321 
322 //        Integer[] test2 = null;//空指针异常
323         Integer[] test2 = new Integer[1];
324         copy = set.toArray(test2);
325         System.out.println(Arrays.toString(test2));//null
326         System.out.println(copy==test2);//false  返回数组是new出来的数组
327         Integer[] test3 = new Integer[10];
328         copy = set.toArray(test3);
329         System.out.println(Arrays.toString(test3));//[1, 2, 3, 4, 5, null, null, null, null, null]
330         System.out.println(copy==test3);//true
331 
332         //如果空间不够,不会拷贝重新分配一个数组
333         //返回值T[] 是一个拷贝后的数组
334 
335 //        test3 = (Integer[])set.toArray();//这个方法返回值是Object[]数组,
336         //Object[]数组是对象,对象之间非继承,实现关系不能强制类型转换。
337         //Object[]并不是Integer[]的父类
338         Object[] obj = set.toArray();
339         copy = new Integer[obj.length];
340         for(int i=0;i<obj.length;i++){
341             System.out.println(obj[i]);
342             copy[i] = (Integer) obj[i];
343         }
344 
345         System.out.println(Arrays.toString(copy));
346     }
347 
348     public static void main(String[] args) {
349 //        test1();//普通添加
350 //        testIntegerSet();//添加包装类
351 //        testStringSet();//添加字符串
352 //        testUserSet();//添加普通类
353 //        testCharArr();//字符串和字符数组补充
354 //        test2();//Hash其它操作,删除,
355 //        test3();//通过迭代器删除
356 //        testIterator();//练习其它容器的迭代器
357 //        test4();//探究什么时候可以删除元素,可变长容器。
358         test5();//其它操作
359 //        Map.Entry
360     }
361 }
362 
363 
364 class User implements Comparable<User> {
365 
366     //没有用
367     @Override
368     public int compareTo(User o) {
369         return -1;
370     }
371 
372     //没有用
373     @Override
374     public boolean equals(Object obj) {
375         return true;
376     }
377 }
复制代码

1.3 HashMap存储探究和LinkedList 容器练习

复制代码
  1 package cn;
  2 
  3 //练习Set --- HashSet -- 其实也就是HashMap
  4 //练习list --- LinkedList
  5 /*
  6 *
  7 * 深入理解 HashSet和LinkedList和ArrayList
  8 * 结论:1.HashMap内部应该是散列存储。
  9 * 2.LinkedList是双向循环链表
 10 * 3.ArrayList是一个变长数组。
 11 *
 12 * */
 13 
 14 import java.util.*;
 15 
 16 
 17 public class Test {
 18     //hash,散列存储,查找,冲突处理
 19     public  static void test1(){
 20         // java.util包下
 21         // Collection --- Set --- HashSet
 22         Set<String> set = new HashSet<>();
 23 //        set.addAll(List.of("A","B","C","D","E","F"));
 24 //        set.addAll(List.of("AA","BB","C","D","E","F"));
 25         set.addAll(List.of("AAA","BBB","C","D","E","F"));
 26 //        set.addAll(List.of("AAAA","BBBB","C","D","E","F"));
 27 //        set.addAll(List.of("AAAAA","BBBBB","C","D","E","F"));
 28 //        set.addAll(List.of("AAAAAA","BBBBB","C","D","E","F"));
 29         set.addAll(List.of("a","b","c","d","e","f"));
 30         set.addAll(List.of("4","5","6","7","8","9"));
 31 
 32         System.out.println(set);
 33 
 34         List<String> arraylist = new ArrayList<String>(set);
 35         arraylist.sort((a,b)->-a.compareTo(b));
 36         System.out.println(arraylist.toString());
 37         set.clear();
 38         set.addAll(arraylist);
 39         System.out.println(set);
 40 
 41         //排序机制
 42         //简单的:
 43         //1.如果addAll的顺序一定那么内部的顺序和原来可以不同,但是唯一。
 44         //其它
 45         //1.调整addAll的顺序可能set的顺序一样,也可能不一样
 46         //结论
 47         //1.取决于元素,也取决于元素添加顺序,取决于相同值元素个数(hash值相同时,往后走可能占下一个元素位置。)
 48         //      1.有些元素一定在一些元素前面;元素个数比较少,位置足够时
 49         //      2.有些元素先添加后添加相对位置不一样。
 50         //      3.如果元素足够多,占相同位置,那么为了让所有元素都存下,所以会有一定算法。
 51         //处理冲突的方法:用一个链表存放相同位置元素,链表超过一定长度变为红黑树。
 52         //总结:1、有排序.但是这个排序规则我们不知道,也不需要知道2、存在冲突处理、使用的是红黑树,能处理大量数据。 53         //3、hashmap 查找,添加,删除效率很高。
 54     }
 55 
 56     //链表集合 java.util.LinkedList;
 57     //remove()方法和List不匹配。
 58     /*
 59     *数据结构:
 60     *利用LinkedList模拟栈和队列的数据结构
 61     *
 62     * */
 63     public static void test2(){
 64         //模拟栈的存储结构  --- 就不用递归了,可以无限查找。
 65         LinkedList<String> list = new LinkedList<>();
 66 //        List<String> list = new LinkedList<>();//不要写成这样,这是一个队列
 67         //内部是一个双向循环链表.
 68         //默认在尾添加,从头删除,类似一个栈。所以不能用它直接来模拟栈,但是可以模拟队列。
 69         //使用addFirst() + remove()模拟栈,
 70         list.addFirst("李四");
 71         list.addFirst("张三");
 72         list.addFirst("王五");
 73         list.addFirst("李四");//元素可以重复
 74         if(list.getFirst()==list.getLast()){
 75             System.out.println("没有额外开辟内存,共用地址");
 76             //1.因为是共用地址,所以可能会有修改的问题。
 77             // 遍历时理论上不会重复除了字符串特殊的
 78             //2.效率很高
 79         }
 80         //出栈:
 81         while(!list.isEmpty()){
 82             String temp = list.remove();
 83             System.out.println(temp.toString());
 84         }
 85         //模拟队列
 86         LinkedList<String> list1 = new LinkedList<>();
 87         list1.add("李四");
 88         list1.add("张三");
 89         list1.add("王五");
 90         list1.add("李四");//元素可以重复
 91 
 92         while(!list1.isEmpty()){
 93             String temp = list1.remove();//参数是boolean类型 用于判断是否更改,废话,
 94             System.out.println(temp.toString());
 95         }
 96 
 97         //其它方法 Collection
 98         //同样是在最后面添加
 99         list1.addAll(List.of("A","B","C","D","E","F","G"));
100         //最后面添加一个元素
101         list1.addLast("A");//和add()一样
102     }
103 
104     //迭代器遍历
105     /*
106     * 迭代器内部实现是一个带有头结点的单向链表
107     *       1、便利的始终是next,下一个元素。 具体方法,hasNext(),next();
108     *               hasNext(),看看下一个元素是否非空。
109     *               next()返回下一个元素值,并且指针自动后移一位
110     *       2、删除当前元素,remove,可能对有些迭代器不适用。这里没有演示
111     * */
112     public static void test3(){
113         LinkedList<String> list1 = new LinkedList<>(List.of("张三","李四","王五","赵六","算法"));
114 
115         Iterator<String> iterator = list1.iterator();
116         System.out.println(iterator.getClass());
117         while(iterator.hasNext()){
118             String temp = iterator.next();
119             System.out.println(temp);
120         }
121 
122     }
123 
124     //其他操作
125     //1、添加/插入,(1)最后添加:add(E);addLast(E);addAll(Collection<E>) (2)第一个位置插入:addFirst(E) (3)某一个位置插入元素add(index,E); addAll(index,collection<E>)
126     //2、删除,(1)删除第一个位置元素 remove(),removeFirst();(2)删除最后一个位置元素,removeLast(3)删除某一位置元素remove(index)(4)删除某个元素remove(Obj)(5)删除一群元素removeAll(Collection);
127     //3、修改,(1)修改set(index,E)(2)清空clear();
128     //4、查找,(1)查找第一个元素,getFirst()(2)查找最后一个元素getLast()(3)查找某个位置元素get(index);
129     //5、将其它Collection容器变为LinkedList 构造方法,或者清空之后,addAll();
130     //LinkedList的插入,删除速度快于ArrayList,但是查找,特别是修改速度很慢,所以必要时候可以将LinkedList转换为ArrayList;
131 
132     public static void test4(){
133         LinkedList<String> list = new LinkedList<>();
134         list.clone();
135         //同样是在最后面添加  index=0
136         list.addAll(List.of("A","B","C","D","E","F","G"));
137         //最后面添加一个元素
138         list.addLast("A");//和add()一样
139         //toString
140         System.out.println(list.toString());
141         //长度,得到某个位置元素
142         //得到某个位置元素
143         System.out.println(list.get(list.size() - 1));
144         //得到第一个位置元素
145         System.out.println(list.getFirst().toString());
146         //得到最后一个元素
147         System.out.println(list.getLast().toString());
148         //是否含有某个元素  --- 和地址无关
149         System.out.println(list.contains("A"));//true
150         System.out.println(list.contains(new String("A")));//true
151         //查找某个元素位置
152         System.out.println(list.indexOf("B"));
153         System.out.println(list.lastIndexOf("A"));
154         System.out.println(list.lastIndexOf("aaa"));
155         //删除某个元素
156         list.remove("AAA");
157         list.remove(1);
158 
159 
160     }
161 
162     public static void main(String[] args){
163         test4();
164     }
165 }
复制代码

1.5 HashSet模拟

复制代码
  1 package com.testhashset;
  2 
  3 //HashSet底层是一个HashMap
  4 //也就是说HashSet添加删除,查看都是通过HashMap实现的,那么它是怎么实现的?
  5 
  6 
  7 import java.util.ArrayList;
  8 import java.util.HashMap;
  9 import java.util.HashSet;
 10 import java.util.List;
 11 
 12 /*
 13 *
 14 * 启发:
 15 * 1、容器套容器案例(一个容器的成员属性可以是容器)
 16 *       用一个map作为实际存储容器。
 17 *       需要理解map的用法
 18 * 2、
 19 *
 20 * */
 21 
 22 public class Test {
 23 
 24     //构造方法--实际是map的方法
 25         //1.构造时,对应初始化存储容器 map
 26         //2.有一个Object类私有最终常量,用于map添加元素
 27 
 28     public static void test(){
 29         //无参初始化
 30         HashSet<String> mySet = new HashSet<>();
 31         //设置初始容量大小
 32         HashSet<String> mySet1 = new HashSet<>(10);
 33         //拷贝一个实例化容器
 34         HashSet<String> mySet2 = new HashSet<>(mySet1);
 35         //
 36         HashSet<String> mySet3 = new HashSet<>(10,10.1f);
 37 
 38         Object temp = new Object();
 39 
 40         //无参初始化
 41         HashMap<String,Object> myMap = new HashMap<>();
 42         HashMap<String,Object> myMap1 = new HashMap<>(10);
 43         //HashSet里面的map只能一个一个添加
 44         //HashSet参数是一个实例化map
 45         HashMap<String,Object> myMap2 = new HashMap<>(myMap);
 46         HashMap<String,Object> myMap3 = new HashMap<>(10,10.1f);
 47 
 48     }
 49 
 50     //Hashset add/addAll添加操作
 51     //其实就是map的put操作
 52     //Hashset add返回值类型是boolean,表示是否成功添加
 53     //Hashmap  put返回值类型是一个V,返回原来对象
 54     //Hashset addAll 返回值是boolean ,表示是否至少添加一个元素
 55 
 56     public static void test1(){
 57         HashSet<String> set1 = new HashSet<>(10);
 58         Object obj = new Object();
 59         HashMap<String,Object> myMap = new HashMap(10);
 60 
 61         System.out.println(set1.add("张三"));//true
 62         System.out.println(myMap.put("张三", obj)==null);//false
 63         System.out.println(set1.add("张三"));//false
 64         System.out.println(myMap.put("张三", obj)==null);//false
 65 
 66         System.out.println(set1.addAll(List.of("李四", "张三")));//true
 67         boolean flag = false;
 68         for (String s :List.of("李四","王五","赵六")){
 69             flag = flag||myMap.put(s, obj)==null;
 70         }
 71         System.out.println(flag);//true
 72     }
 73 
 74     //Hashset remove()removeAll()删除操作 clean()清空
 75     //其实就是map的remove clean()清空操作
 76 
 77     public static void test2(){
 78         HashSet<String> set = new HashSet<>(10);
 79         Object obj = new Object();
 80         HashMap<String,Object> map = new HashMap(10);
 81         set.add("张三");
 82         map.put("张三",obj);
 83 
 84         System.out.println(set.remove("张三"));//true
 85         //就是通过key删除
 86         System.out.println(map.remove("张三")==null?false:true);//true
 87 
 88         set.addAll(List.of("张三","李四"));
 89         System.out.println(set.removeAll(List.of("张三", "李四", "王五")));//true
 90 
 91         for (String s :List.of("张三","李四")){
 92             map.put(s,obj);
 93         }
 94 
 95         //不能直接删除一群,只能一个一个操作
 96 
 97         boolean flag = false;
 98         for (String s :List.of("张三", "李四", "王五")){
 99             flag = flag||map.remove(s)!=null;//true
100         }
101         System.out.println(flag);//true
102 
103         set.clear();
104         map.clear();
105     }
106 
107     //HashSet contains() containsAll()方法
108     //也是map的对key的操作
109     //同样不能一次判断群
110 
111     public static void test3(){
112         HashSet<String> set = new HashSet<>(10);
113         Object obj = new Object();
114         HashMap<String,Object> map = new HashMap(10);
115         set.add("张三");
116         set.addAll(List.of("李四","王五"));
117         map.put("张三",obj);
118         for (String s :List.of("李四","王五")){
119             map.put(s,obj);
120         }
121 
122         //判断是否包含某个元素
123         System.out.println(set.contains("张三"));//true
124         System.out.println(map.containsKey("张三"));//true
125 
126 
127         boolean flag = true;
128         //判断是否包含一群元素,必须都有
129         for (String s :List.of("张三", "李四", "王五")){
130             flag = flag&&map.containsKey(s);
131         }
132         System.out.println(set.containsAll(List.of("张三", "李四", "王五")));//true
133         System.out.println(flag);
134 
135         flag = true;
136         System.out.println(set.containsAll(List.of("张三", "李四", "王五", "赵六")));//false
137         for (String s :List.of("张三", "李四", "王五", "赵六")){
138             flag = flag&&map.containsKey(s);
139         }
140         System.out.println(flag);//false
141 
142     }
143 
144     //HashSet不存在修改操作,HashMap也不存在修改
145 
146     public static void main(String[] args) {
147 //        test();//构造方法测试
148 //        test1();//add/addAll方法模拟
149 //        test2();//remove/removeAll方法模拟
150         test3();
151     }
152 }
复制代码

 1.6HashMap效率测试

复制代码
  1 package com.testhashmap;
  2 
  3 /*
  4 *
  5 * HashMap存储结构用在HashSet里面了。
  6 *
  7 * 1、概述:
  8 *       1、数组的散列存储能够实现通过关键字找到值,但是随着元素个数增加,冲突概率增加,产生冲突需要解决,否则影响查找,
  9 *           冲突解决可以采用拉链法,建立一个链表存储多余元素
 10 *       2、但是链表查找效率低,于是有了红黑树。在链表个数超过一定数量的时候链表会变成一个红黑树,有了红黑树,我丝毫看不到链表的优势,除了实现简单。
 11 * 2、怎么证明确实是
 12 *       1、哈希函数
 13 *       2、冲突处理
 14 *       3、红黑树。
 15 *
 16 *       方法,通过比较LinkedList,ArrayList 增删改查的时间,估算用的是什么了。
 17 *
 18 *
 19 * */
 20 
 21 import java.util.*;
 22 
 23 public class TestHashMap {
 24     public static void  test1(){
 25         HashMap<User,Integer> map = new HashMap<>();
 26         ArrayList<User> list1 = new ArrayList<>();
 27         LinkedList<User> list2 = new LinkedList<>();
 28 
 29         //首先是10000个作为初始化的元素
 30         for(int i =0;i<10000;i++){
 31             list1.add(new User());
 32             map.put(new User(),i);//无所谓,也可以单独拿出来写
 33         }
 34         //拷贝list1
 35         list2.addAll(list1);
 36 
 37         //插入的用时对比---就拿添加为例,因为map只有put
 38 
 39         //100000次
 40         long begin = System.currentTimeMillis();
 41         for(int i = 0;i<100000;i++){
 42             map.put(new User(),i);
 43         }
 44         long end = System.currentTimeMillis();
 45         System.out.println(end-begin);
 46         begin = System.currentTimeMillis();
 47         for(int i = 0;i<100000;i++){
 48             list1.add(new User());
 49         }
 50         end = System.currentTimeMillis();
 51         System.out.println(end-begin);
 52         begin = System.currentTimeMillis();
 53         for(int i = 0;i<100000;i++){
 54             list2.addLast(new User());
 55         }
 56         end = System.currentTimeMillis();
 57         System.out.println(end-begin);
 58 
 59         //list并不一定每次都是在最后面添加
 60         //这里添加10万个Hashmap用时52毫秒,速度已经很好了
 61         //那么先试一下让list随机插入的后果。 就在10000的位置插入
 62 
 63         for(int i = 0;i<100000;i++){
 64             list1.add(10000,new User());
 65         }
 66         end = System.currentTimeMillis();
 67         System.out.println(end-begin); //
 68         begin = System.currentTimeMillis();
 69         for(int i = 0;i<100000;i++){
 70             list2.add(10000,new User());
 71         }
 72         end = System.currentTimeMillis();
 73         System.out.println(end-begin);//
 74         begin = System.currentTimeMillis();
 75         for(int i = 0;i<100000;i++){
 76             map.put(new User(),i);
 77         }
 78         end = System.currentTimeMillis();
 79         System.out.println(end-begin);//
 80 
 81         //总结如果是每次都是在最后面添加那么不用考虑了,数组Arraylist
 82         //如果数据量很大,别用ArrayList和LinkedList,最少不要用LinkedList
 83         //HashMap还是一如既往的稳定 31毫秒
 84     }
 85 
 86     public static void test2(){
 87         //补充元素150000
 88         HashMap<Integer,Integer> map = new HashMap<>();
 89         ArrayList<Integer> list1 = new ArrayList<>();
 90         LinkedList<Integer> list2 = new LinkedList<>();
 91         for(int i =0;i<150000;i++){
 92             list1.add(i);
 93             map.put(i,i);
 94         }
 95         list2.addAll(list1);
 96 
 97         //删除 10000 - 100000的元素
 98         long begin = System.currentTimeMillis();
 99         for(int i = 100000;i>=10000;i--){
100             map.remove(i);
101         }
102         long end = System.currentTimeMillis();
103         System.out.println(end-begin);
104 
105         begin = System.currentTimeMillis();
106         for(int i = 100000;i>=10000;i--){
107             list1.remove(i);
108         }
109         end = System.currentTimeMillis();
110         System.out.println(end-begin);
111         begin = System.currentTimeMillis();
112         for(int i = 100000;i>=10000;i--){
113             list2.remove(i);
114         }
115         end = System.currentTimeMillis();
116         System.out.println(end-begin);
117 
118 
119         begin = System.currentTimeMillis();
120         map.clear();
121         end = System.currentTimeMillis();
122         System.out.println(end-begin);
123         begin = System.currentTimeMillis();
124         list1.clear();
125         end = System.currentTimeMillis();
126         System.out.println(end-begin);
127         begin = System.currentTimeMillis();
128         list2.clear();
129         end = System.currentTimeMillis();
130         System.out.println(end-begin);
131     }
132     //一言难尽
133 
134     //查找 -- 找某个位置的元素应该是ArrayList快
135 
136     public static void test3(){
137         HashMap<Integer,Integer> map = new HashMap<>();
138         ArrayList<Integer> list1 = new ArrayList<>();
139         LinkedList<Integer> list2 = new LinkedList<>();
140         for(int i =0;i<150000;i++){
141             list1.add(i);
142             map.put(i,i);
143         }
144         list2.addAll(list1);
145 
146         //查找 10000 - 100000的元素
147         long begin = System.currentTimeMillis();
148         for(int i = 100000;i>=10000;i--){
149             map.containsKey(i);
150         }
151         long end = System.currentTimeMillis();
152         System.out.println(end-begin);
153 
154         begin = System.currentTimeMillis();
155         for(int i = 100000;i>=10000;i--){
156             list1.contains(i);
157         }
158         end = System.currentTimeMillis();
159         System.out.println(end-begin);
160         begin = System.currentTimeMillis();
161         for(int i = 100000;i>=10000;i--){
162             list2.contains(i);
163         }
164         end = System.currentTimeMillis();
165         System.out.println(end-begin);
166     }
167     //总结:Hash是真的牛,全能,显然就是用了Hash函数+红黑树(难点)
168     //删除和查找,LinkedList就离谱,越来越菜。
169 
170     //神装大佬吊打2个小弟
171 
172     //修改操作
173     public static void test4(){
174         HashMap<Integer,String> map = new HashMap<>();
175         ArrayList<Integer> list1 = new ArrayList<>();
176         LinkedList<Integer> list2 = new LinkedList<>();
177         for(int i =0;i<150000;i++){
178             list1.add(i);
179             map.put(i,"1");
180         }
181         list2.addAll(list1);
182 
183         long begin = System.currentTimeMillis();
184         Set<Integer> integers = map.keySet();
185 //        for(int i = 100000;i>=10000;i--){
186 //
187 ////          String temp =  map.get(i); temp = " "+i;//因为String类型和包装类存在自动包装机制,所以难为它了
188 //
189 //        }
190         //由于没有合适方法,内部还是通过迭代器一个一个找,所以这一轮认输算了。
191         //再试一下
192         //entries 是一个Set容器,但是元素也是一个容器,
193 //        Set<Map.Entry<Integer, String>> entries = map.entrySet();
194 //        for(int i = 100000;i>=10000;i--){
195 //
196 //        }
197         //迭代器--这样就慢了
198         //突然发现迭代器也改不了,
199 
200 
201         long end = System.currentTimeMillis();
202         System.out.println(end-begin);
203 
204         begin = System.currentTimeMillis();
205         for(int i = 100000;i>=10000;i--){
206             list1.set(i,i+1);
207         }
208         end = System.currentTimeMillis();
209         System.out.println(end-begin);
210         begin = System.currentTimeMillis();
211         for(int i = 100000;i>=10000;i--){
212             list2.set(i,i+1);
213         }
214         end = System.currentTimeMillis();
215         System.out.println(end-begin);
216     }
217     public static void test5(){
218         HashMap<Integer,User> map = new HashMap<>();
219         ArrayList<Integer> list1 = new ArrayList<>();
220         LinkedList<Integer> list2 = new LinkedList<>();
221         for(int i =0;i<150000;i++){
222             list1.add(i);
223             map.put(i,new User());
224         }
225         list2.addAll(list1);
226 
227         long begin = System.currentTimeMillis();
228         Set<Integer> integers = map.keySet();
229         for(int i = 100000;i>=10000;i--){
230             map.get(i).value = i;
231         }
232         long end = System.currentTimeMillis();
233         System.out.println(end-begin);
234 
235         begin = System.currentTimeMillis();
236         for(int i = 100000;i>=10000;i--){
237             list1.set(i,i+1);
238         }
239         end = System.currentTimeMillis();
240         System.out.println(end-begin);
241         begin = System.currentTimeMillis();
242         for(int i = 100000;i>=10000;i--){
243             list2.set(i,i+1);
244         }
245         end = System.currentTimeMillis();
246         System.out.println(end-begin);
247     }
248 
249     public static void main(String[] args) {
250 //        test1();//添加和插入测试,
251 //        test2();//删除测试
252 //        test3();//查找测试
253         test5();
254     }
255 }
256 
257 //随意定义一个类,这个类存值。
258 
259 class User{
260     public int value;
261 //    public String value;
262 }
复制代码

2.1 TreeMap练习1

复制代码
 1 package com.day17;
 2 
 3 import java.util.TreeMap;
 4 
 5 public class TestTreeMap {
 6     //key是有序的,当然也是唯一的。
 7     public static void test1( ){
 8         //String类的比较器
 9         TreeMap<String,String> map1 = new TreeMap<>();
10         map1.put("1","1");
11         map1.put("2","1");
12         map1.put("3","1");
13         map1.put("4","1");
14         map1.put("5","1");
15         map1.put("11","1");
16         map1.put("111","1");
17         map1.put("1111","1");
18         map1.put("11111","1");
19         //{1=1, 11=1, 111=1, 1111=1, 11111=1, 2=1, 3=1, 4=1, 5=1}
20         System.out.println(map1);
21     }
22 
23     public static void testComparable(){
24         TreeMap<Student,String> map1 = new TreeMap<>();
25         Integer i = 1;
26         for(;i<=10;i++){
27             try {
28                 map1.put(new Student(i,i.toString()),i.toString());
29             }catch (ClassCastException e){
30                 System.out.printf("添加第%d个元素异常%n",i);
31             }
32         }
33         System.out.println(map1);
34     }
35     public static void main(String[] args){
36 //        test1();
37         testComparable();
38     }
39 
40 
41     //原理就是一个比较器。不能排序的(Comp没有给我们默认实现)自己写排序,
42     //乱序--二分排序,(数组)
43     //怎么让自定义类型排序
44         //初始化时传递Comparator接口实现类--
45             //--初始化可以初始化常量
46             //comparator.compare(k1, k2) 不能为映射中的任何键 k1 和 k2 抛出 ClassCastException(强制类型转换异常)
47         //初始化不初始化接口实现类
48             //插入map的所有键(KEY)必须实现可比较的接口Comparable<Student>。
49             // 此外,所有这些键必须相互可比:k1.compareTo(k2)不能为映射中的任何键k1和k2抛出ClassCastException。
50 
51 }
52 
53 
54 class Student implements Comparable<Student>{
55     private int id;
56     private String name;
57     Student(){
58 
59     }
60     Student(int id, String name){
61         this.id = id;
62         this.name = name;
63     }
64     @Override
65     public int compareTo(Student o) {
66         if(o==null){
67             return -1;
68         }
69         return this.id-o.id;
70     }
71     @Override
72     public String toString(){
73         return "{"+this.id+","+this.name+",}";
74     }
75 }
复制代码

2.2TreeMap练习2Map集合遍历

复制代码
  1 package com.testtreemap;
  2 
  3 import java.util.*;
  4 import java.lang.String;
  5 public class TestTreeMap {
  6     //HashMap已经神装了,干嘛还要TreeMap
  7     //TreeMap有什么特有的
  8             //发现内部有一个比较器,优化了红黑树的比较,也就是说这次是真的可以随心所欲实现没有重复值了
  9             //key一样时,后者value替代前者,但是key地址就不替代了。
 10 
 11     //构造方法,比较器
 12     //添加元素
 13     public static void test1(){
 14         //说明:
 15         //1、String类已经实现了Comparable<String>接口(自然比较器,可以比较的,不要把接口名字写错误,),所以它有接口方法compareTo(String);
 16         //2、强制类型转换。我可以变成接口实现类啊,用接口实现类就是用我。我是多种实现的一个。
 17 //        TreeMap<String, Integer> map = new TreeMap<>((a,b)->a.compareTo(b));
 18         //因为方法中存在的强制类型转换,所以没有必要写
 19         TreeMap<String,Integer> map = new TreeMap<>();
 20         map.put("张三",1);
 21         map.put("李四",2);
 22         map.put("王五",3);
 23         map.put("张三",4);
 24         //相同key时,后面的或默认把前面的value覆盖了
 25         //这点不同于HashMap
 26         System.out.println(map);
 27     }
 28 
 29     //添加一群元素
 30 
 31     public static void test2(){
 32         TreeMap<String,Integer> map = new TreeMap<>();
 33         //果然,map也可以putall
 34         map.putAll(Map.of("张三",1,"李四",2));
 35 
 36     }
 37 
 38 
 39     //Treemap集合遍历
 40     //也适用于HashMap
 41 
 42     //Map.Entry内部类
 43     /*
 44     *
 45     * 1、Map.Entry就是实例化Map的类的元素类型,所有Map.Entry的具体集合组成了Map集合。
 46     * 猛一下子没有明白过来。
 47     *       内部类就是专门定义的数据结构(类型+操作)。
 48     * 2、迭代器泛型元素类型的就是集合元素类型。
 49     *       迭代器就是容器本身产生的为了遍历元素用的,所以类型应该匹配。
 50     *第一次遇到内部类。
 51     * 易错点:
 52     * 1.认为Map.Entry是一个类似Map一样的容器。
 53     *       原因:没有正确理解泛型,理解容器。
 54     *           并不是泛型类并不一定是容器,容器也不一定是泛型的。
 55     *案例
 56     * 迭代器(流技术)有点像数据库中的resultSet
 57     *
 58     * */
 59 
 60     public static void test3(){
 61 
 62         TreeMap<String,Integer> map = new TreeMap<>();
 63         map.putAll(Map.of("张三",1,"李四",2,"王五",3,"赵六",4));
 64         //通过迭代器遍历
 65         Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
 66         while(it.hasNext()){
 67             Map.Entry<String, Integer> entry = it.next();
 68             System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
 69         }
 70         //通过TreeMap的keySet()方法
 71         //返回值是key的集合,类型是Set集合,
 72         // Set是一个接口,实际对象是TreeMap返回的一个Set接口的实例化对象。
 73         Set<String> keys = map.keySet();
 74         Iterator<String> it1 = keys.iterator();
 75         //遍历所有key对象。
 76         while(it1.hasNext()){
 77             System.out.println("key="+it1.next());
 78         }
 79 
 80         //通过TreeMap的Values()
 81         //返回是一个values集合,类型是Collection
 82         //Collection也是一个接口,实际对象是TreeMap返回的一个Collection 接口的实例化对象。
 83         Collection<Integer> values = map.values();
 84         Iterator<Integer> it2 = values.iterator();
 85         //遍历所有values对象
 86         //自动拆箱
 87         while(it2.hasNext()){
 88             System.out.println("value="+it2.next());
 89         }
 90 
 91         //也可用for:in语句,也可遍历容器
 92         for (int i:values){
 93             System.out.println("value="+i);
 94         }
 95 
 96         for(String key:keys){
 97             System.out.println("key="+key);
 98         }
 99     }
100 
101     public static void main(String[] args) {
102 //        test1();
103 //        test2();
104         test3();
105     }
106 }
复制代码

 

补充 1.TreeMap内部排序机制模拟

复制代码
 1 package cn;
 2 
 3 import java.util.Comparator;
 4 
 5 public class FX2 <E>{
 6 
 7     public E[] es;
 8 //    Comparable comparable=null;// 易错点,不能要这个,不能两个数比较
 9     private final Comparator<E> comparator;
10 
11     //方法中可以直接用?,更加灵活
12     FX2(){
13         comparator = null;
14     }
15 
16     FX2(Comparator<E> comparator){
17         this.comparator = comparator;
18     }
19 
20 
21     //冒泡排序
22     //升序
23     void sort(){
24         if(es==null||es.length==0){
25             return;
26         }
27         if(comparator!=null){
28             boolean flag=false;
29             for (int i=0,len=es.length;i<len;i++){
30                 flag=true;
31                 for (int j =0;j<len-i-1;j++){
32                     if (comparator.compare(es[j],es[j+1])>0){
33                         flag = false;
34                         E e = es[j];
35                         es[j] = es[j+1];
36                         es[j+1] = e;
37                     }
38                     if (flag){
39                         break;
40                     }
41                 }
42             }
43         }
44         else{
45             System.out.println(es[0] instanceof Comparable);
46             //强制类型转换可能存在异常  -- 或者判断一下es是否是
47             try {
48                 System.out.println((Comparable) es[0]);
49             }
50             catch(ClassCastException e){
51                 e.printStackTrace();
52                 System.out.println("强制类型转换异常,您传递的类没有实现Comparable接口,请实现接口,或者在传递比较器");
53                 return ;
54             }
55 
56             boolean temp = false;
57             for (int i = 0,len = es.length;i<len;i++){
58                 temp = true;
59                 for (int j = 0;j<len-1-i;j++){
60                     if(((Comparable)es[j]).compareTo(es[j+1])>0){
61                         temp = false;
62                         E t = es[j];
63                         es[j] = es[j+1];
64                         es[j+1] = t;
65                     }
66                 }
67                 if(temp){
68                     break;
69                 }
70             }
71         }
72     }
73 
74 }
复制代码

 

补充:

1.Map实现类虽然不能修改,但是可以添加key相同的元素达到修改。

2.Map的元素类型是Map.Entry

3.HashMap操作是以key的HashCode,和equals方法为基础的

 

个人总结

1、TreeMap它的特点是什么,它是怎么实现的?
TreeMap;
特点:
1、继承抽象类AbstractMap,抽象类继承Map接口,是一个实例化对象。
2、有一个私有的,常量成员属性 Comparator类型的自然比较器comparator。
即:private final Comparator<? super K> comparator;
3、key顺序可控。
实现原理:
控制put
1、通过私有常量比较器接口通过比较每一个对象,如果对象和已有对象值相等那么就会覆盖前面的value保证key不会重复
多态--使用接口就是使用实现类
a、可以在初始的时候传递实例化对象,给接口赋值。这样用接口就使用实例化对象的方法。
b、key类可以实现Comparable<E>接口,这样添加元素的时候会自动使用key
a、b确实有,它内部通过if else实现了。

反之,如果不仅没有在初始时候初始化化是有最终比较器接口(手动赋值为null),而且Key也没有实现接口
那么比较器是自动调用的,put会抛出类转换异常ClassCastException
如果key实现了比较器,且初始化传递了参数,那么会先用初始化的比较器,内部的就不用了。

2、HashSet存储利用了HashMap,为什么要用到HashMap,它的特点是什么?应用场景
2.1
1、HashMap实现了Map接口,1、采用数值(散列存储)+链表/红黑树(冲突处理)快速实现存取,删除,查找。2、Key值不能重复(HashMap相同地址的元素后者Value覆盖前者,但是key地址不覆盖),所以Key元素还是保留前者。
2、HashMap实现原理不同于TreeMap,操作起来更加简单。

HashSet用HashMap数据结构后能干什么?
可以利用Hash存储结构存放元素,
可以利用HashMap的操作实现删除,添加, 查找。

2.2
HashMap实现原理
1、散列存储
关键字,存储地址,存储表(容器)
1、散列函数的定义域必须包含全部需要存储的关键字,值域范围依赖于散列表的大小或地址范围
2、散列函数计算出来的地址应该能等概率、均匀地分布在整个地址空间,减少冲突发生。
3、散列函数应尽量简单,能够在较短的时间内计算出任意关键字对应的散列地址
hash函数(其中一个)
1、直接定址法,没有冲突(线性函数)
2、除留余数法(关键),(存在冲突)
3、数字分析法,分部不均匀的
4、平方取中法
5、折叠法

2、冲突处理,
拉链法:链表+红黑树
3、存储顺序/hash函数
1、一定有序,有序是基础,但是我们不需要研究。
2、这个顺序并不是A一定在B前面,1一定在2前面,就是和平常排序不同。

2.3 HashSet特点
建立关键字和存储地址的映射关系
底层使用哈希表实现
元素不可重复
排列无序(准确说,应该是其不保证有序。迭代器在遍历HashSet时,大多情况下是无序的,但也可能由于巧合,使其输出恰好为有序,这也是允许的。所以你的程序不应该依赖这个巧合的有序情况,而应该按照无序这种普适的情况进行处理)
存取速度快
线程不安全

2.4HashSet应用场景
集合,元素不能重复,
String,包装类都会自动打包

3、LinkedList容器内部机制,它的特点是什么?
LinkedList是一个双向循环链表
插入删除快,可以模拟数据结构栈和队列,
4、ArrayList容器内部机制,它的特点是什么?
ArrayList是一个变长(动态)数组
随机存储,比较灵活,数值长度可变,但是删除,插入用时比较长。
5、HashMap存储原理,它的特点是什么?
存储原理见2.
特点
1、key上元素不能重复,否则保留前者key值,后者value值替代前者。
2、插入,删除,查找速度都很快

6、简述一下迭代器的特点和作用。
特点:
1、每个容器实现类都可返回一个迭代器,迭代器我们就不用new了。
2、利用了流技术,一般只能往后遍历。
3、迭代器也用到了泛型。元素类型就是容器元素类型。

作用
1、迭代器的作用是帮助容器快速遍历,查找,删除元素。

7、简述一下Map.Entry内部类的特点和作用。
7.1特点:
1、是Map接口的内部类。
2、利用泛型,但不是容器。

7.2
1、专门为所有Map对象定义的一个数据结构,方便内部成员使用。
2、一个元素不仅存储了key值,还同时存储了value值
可同时对key,value操作。

8、一个异常
ClassCastException//类型转换异常,
出现原因:
1、泛型中设置了,强制类型转换失败,
2、既没有实例化比较器,也没有实现Comparable接口

2022/9/23
集合遍历
  第一种方式:迭代器
  第二种方式:内置的方法,foreach方法
  第三种:可以利用流
  第四种:可以用for:in循环,
总结:
1.时刻记住遍历的底层元素是谁就行了,还有就是记住转换关系
  底层元素就是泛型指定的元素
2.Map遍历的需要先变为Set<Map.Entry<Key,Value>>:然后按照遍历Set集合的方式遍历元素。不能直接遍历元素
3.Set,List遍历元素类型就是泛型的元素类型,可以直接遍历元素。


集合和mybatis
  list集合作为方法返回值
  List集合作为返回值可以接收多行查询的结果(List集合遍历,添加元素速度最快,并且是一个长度可变的数组
  map集合作为方法的返回值,
  map元素是键值对,所以map可以看做抽象的实体类

集合和ajax请求
  作为参数
  Map可以作为参数,作用等同于实体类,非常灵活
  作为返回值
  map集合返回给前端,前端收到的是一个json对象。这和传统的字符串不一样,非常方便。 key和Value类型都是Object
  list集合返回给前端,前端收到的是一个Object数组。
总结:map,list是一个非常好的数据结构,
posted @   liu/564  阅读(499)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示