1.集合框架体系
集合主要分为两组:单列集合(collection),双列集合(map)
单列集合(collection接口)
双列集合(map接口)
2.Collection接口
(1).常见的方法
*/
public class arraylist_ {public static void main(String[] args) {//常用方法,用arrayList类演示ArrayList<String> fruits = new ArrayList<>();//1.add 添加单个元素fruits.add("苹果");fruits.add("香蕉");fruits.add(1,"橘子");//在指定位置插入,香蕉后面//2.remove删除指定元素,可以是内容,可以是下标,并返回该元素fruits.remove("苹果");fruits.remove(0);//3.contains查找元素是否存在fruits.contains("梨");//4) size:获取元素个数System.out.println(fruits.size());//5)isEmpty:判断是否为空System.out.println(fruits.isEmpty());//6)clear:清空fruits.clear();//7)addAll:添加多个元素ArrayList<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");fruits.addAll(list);fruits.addAll(2,list);//在3后面加入list里的所有元素//8)containsAll:查找多个元素是否都存在System.out.println(fruits.containsAll(list));//true//9)removeAll: 删除多个元素fruits.removeAll(list);//10.get(index)获取指定位置的元素System.out.println(fruits.get(1));//11.indexOf()返回元素在集合首次出现的位置System.out.println(fruits.indexOf("1"));//12.LastindexOf()返回元素在集合最后次出现的位置//13.set(index,object)将指定位置的元素替换为obj,可以是单个元素,可以是集合System.out.println(fruits.set(1,"a"));//14.subList(formIndex,toIndex)返回从开始索引到结束索引的子集合[)}
}
(2).collection接口遍历元素的方法
1).使用iterator(迭代器)
- Iterator对象称为迭代器,主要用于遍历 Collection 集合中的元素。
- 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
- Iterator 仅用于遍历集合,lterator 本身并不存放对象。
- 在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。
- 如果希望再次遍历,需要重置迭代器iterator=list.iterator()
public class b {public static void main(String[] args) {ArrayList<String> fruits = new ArrayList<>();// 添加元素fruits.add("苹果");fruits.add("香蕉");fruits.add("橙子");// 使用迭代器遍历集合,while(itertor)快捷键itit//查看所有快捷键ctrl+gIterator<String> iterator = fruits.iterator();while (iterator.hasNext()) {String fruit = iterator.next();System.out.println(fruit);}//第二次遍历,重置迭代器iterator=fruits.iterator();while (iterator.hasNext()) {String frult2 = iterator.next();System.out.println(frult2);}}}
2).增强for
- 增强for是简化版的iterator
- 只能用于遍历集合和数组
public class c {public static void main(String[] args) {ArrayList<String> fruits = new ArrayList<>();// 添加元素fruits.add("苹果");fruits.add("香蕉");fruits.add("橙子");// 使用增强的 for-each 循环遍历集合//快捷键Ifor (String fruit : fruits) {System.out.println(fruit);}}
}
3).普通for循环
public class f {public static void main(String[] args) {ArrayList<Integer> fruits = new ArrayList<>();// 添加元素fruits.add(1);fruits.add(2);fruits.add(3);// 使用增强的 for-each 循环遍历集合//快捷键Ifor (int i = 0; i < fruits.size(); i++) {int j = fruits.get(i);//如果添加的是String类型的,get()返回的是IntegerSystem.out.println(j);}System.out.println(fruits.get(1));}
}
3.List
(1).ArrayList
1).注意事项:
- 可以放任何值,包括null
- ArrayList 基本等同于Vector,除了 ArrayList是线程不安全(执行效率高) 看源码在多线程情况下,不建议使用ArrayList
2).ArrsyList底层结构分析:
transient:表示该属性不会被序列化
(2).Vector
1).定义说明:
- Vector底层也是一个对象数组,protected Object[ ] elementData;
- Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized
- 在开发中,需要线程同步安全时,考虑使用Vector
2).扩容机制
(3).LinkedList
1).定义说明
2). 底层结构
(4).ArrayList和LinkedList比较
4.Set
(1).常用方法
和list接口一样,Set也是Collection的子接口,因此,常用方法和Collection一样
注:虽然Set的顺序不是存放顺序,但是这个顺序是固定的。
(2).Set接口遍历方式
迭代器、增强for、不能使用普通for(索引的方式来获取)
public class HashSet {public static void main(String[] args) {Set set = (Set) new HashSet();set.add("a");set.add("b");set.add("b");set.add(null);set.add(null);//不重复//方式一:迭代iteratorIterator iterator = set.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}//方式二:for (Object o :set) {System.out.println(o);}//不能使用普通for循环}
}
(3).HashSet
1).定义说明:
1)HashSet实现了Set接口
2)HashSet实际上是HashMap。HashMap的底层是(数组+链表+红黑树).
3)可以存放null值,但是只能有一个null
4)HashSet不保证存放元素的顺序和取出顺序一致。
2).HashSet添加元素底层源码:
public class a {public static void main(String[] args) {Set hashSet =(Set) new HashSet();System.out.println(hashSet.add(new Dog("小黑")));//tSystem.out.println(hashSet.add(new Dog("小黑")));//tSystem.out.println(hashSet.add(new String("小黑")));//tSystem.out.println(hashSet.add(new String("小黑")));//F,添加不进去,看底层源码}
}
class Dog{private String name;public Dog(String name) {this.name = name;}
}
分析:
equals()方法和hash()方法同时出现。快捷键选择
HashSet扩容机制:
(4).LinkedHashSet
定义说明:
1)LinkedHashSet 是 HashSet 的子类。
2)LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组+双向链表
3) LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
4)LinkedHashSet 不允许添重复元素
(5).treeset
treeset的底层就是treeMap
public class a {public static void main(String[] args) {//1.不做任何处理,创建TreeSet时,是无序的//2.现在让它按照字符串大小排序//3.使用TreeSet 提供的一个构造器,可以传入一个比较器(匿名内部类)//并指定排序规则TreeSet<Object> treeSet = new TreeSet<>(new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {//按照首字母大小return ((String)o1).compareTo((String) o2);//调用字符串的compareto方法,比较字符大小//前-后,然后返回//这种添加一个a,可以成功添加//按照长度大小排序//return ( (String)o2).length() - ( (String)o1).length();//这个时候再添加一个长度为1的,添加失败,已经有一个长度为1的了}});treeSet.add("aaaa");treeSet.add("taa");treeSet.add("ka");treeSet.add("l");treeSet.add("a");System.out.println(treeSet);//1.构造器把传入的比较器对象赋给了,TreeeSet的底层的reeMap的属性this.comparator//2.在调用add方法时,底层会动态绑定到我们的匿名类对象compare}
}
5.Map接口(双列)
(1).map接口的特点:
synchronized
//1.k-v 最后是 HashMapSNode node = newNode(hash,key,value,null)
//2.K-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry,而一个Entry对象就有k,v EntrySet<Entry<K,V>>,只是指向k和v。
(2).常用方法
1)put:添加,如果key一样,value不一样,会发生替换
2)remove:根据键删除映射关系
3) get: 根据键获取值
4)size:获取元素个数
5)isEmpty:判断个数是否为0
6)clear:清除
7)containsKey:查找键是否存在
(3).Map集合遍历的6种方法
public class a {public static void main(String[] args) {HashMap<Object, Object> map = new HashMap<>();map.put("1","one");map.put("2","two");map.put("3","two");map.put("4","two");map.put("5","two");//第一组:先取出key,通过Key取出对应的value//keySet集合里面存放的是keySet<Object> keyset = map.keySet();//(1)增强forfor (Object o :keyset) {System.out.println(map.get(o));}//(2)迭代器Iterator iterator= keyset.iterator();//这里是keyset.iterator不是map,数据在keyset里面while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}//第二组:把values集合取出来// values集合(里面存放的是value值)Collection<Object> values = map.values();//使用3种方法取出value(增强for,iterator)//(1).增强forfor (Object o :values) {System.out.println(o);}//(2)iteratorIterator<Object> iterator1 = values.iterator();while (iterator1.hasNext()) {Object next = iterator1.next();System.out.println(next);}//第三组:通过entrySet来获取Set<Map.Entry<Object, Object>> entries = map.entrySet();//(1).增强forfor (Object o :entries) {Map.Entry m=(Map.Entry) o;//先把它转换为Map.EntrySystem.out.println(m.getKey()+""+m.getValue());}
// (2).迭代器Iterator<Map.Entry<Object, Object>> iterator2 = entries.iterator();while (iterator2.hasNext()) {Map.Entry<Object, Object> next = iterator2.next();//向下转型Map.Entry m=(Map.Entry) next;//next的类型是HashMap$NodeSystem.out.println(next.getKey()+""+next.getValue());}}
}
(4).HashMap底层机制及源码剖析
table数组+链表+红黑数(长度大于64变树)
数组元素都是HashMap$Node(k-v)
(5).HashTable
基本介绍:
1)存放的元素是键值对: 即 K-V
2)hashtable的键和值都不能为null, 否则会抛出NullPointer
3)hashTable 使用方法基本上和HashMap一样
4)hashTable 是线程安全的(synchronized),hashMap 是线程不安全的
(6).Properties
基本介绍:
public class properties_ {public static void main(String[] args) {Properties properties = new Properties();//1.添加,k,v不能为空properties.put("a",1);properties.put("a",2);//替换上面的properties.put("b",1);properties.put("c",3);//properties.put("a",null);异常System.out.println(properties);//通过k获取值System.out.println(properties.get("a"));//2//2.删除properties.remove("lic");System.out.println(properties);//3.修改properties.put("c",4);}
}
(7).treeMap
public class d {public static void main(String[] args) {//1.使用默认构造器Treemap是无序//2.现在按照字符K大小排序//3.构造器把传入的,compator接口的匿名内部类,传给TreeMap//4.调用put//4.1第一次添加,把k-v封装到Entry对象,放入root//4.2第二次添加,遍历所有的key,给当前的k找个合适位置//通过动态绑定,使用我们的匿名内部类来比较k(如果compater比较的是长度,再添加一个长度相等的,不能添加)//如果按照字符添加“a”,添加成功TreeMap<Object, Object> tp = new TreeMap<>(new Comparator<Object>() {//匿名内部类@Overridepublic int compare(Object o1, Object o2) {//return ((String)o1).compareTo((String) o2);//按照长度排序return ((String) o2).length()-((String) o1).length();}});tp.put("qwq","1");tp.put("tom","1");tp.put("kisss","1");tp.put("siml","1");System.out.println(tp);}
}
6.如何选择集合实现类
linkedhashmap:数组+双链表
7.collections工具类
public class a {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("c");list.add("d");list.add("e");//reverse(List): 反转 List 中元素的顺序Collections.reverse(list);System.out.println("元素反转"+list);//shuffle(List):对 List 集合元素进行随机排序//Collections.shuffle(list);//System.out.println(list);//sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序//按照字符串顺序Collections.sort(list);//sort(List,Comparator): 根据指定的 Comparator 产生的顺序对 List 集合元素//现在按照字符串长度大小排序Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return ((String)o1).length()-((String)o2).length();}});System.out.println("按长度排序"+list);//swap(List,int, int): 将指定 List 集合中的 i 处元素和 j 处元素进行交换Collections.swap(list,0,1);System.out.println(list);//Object max(Collection):根据元素的自然顺序,返回集合的最大元素System.out.println(Collections.max(list));//Object max(Collection,Comparator):根据Comparator给的顺序,返回集合的最大元素//比如,返回长度最值的元素Collections.max(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return ((String)o1).length()-((String)o2).length();}});//Object min(Collection):根据元素的自然顺序,返回集合的最小元素//Object min(Collection,Comparator):根据Comparator给的顺序,返回集合的最小元素//和max一样//int frequency(list, src):list是集合,src是要统计的字符串System.out.println("a出现的次数"+Collections.frequency(list,"a"));//void copy (list,src):将src的内容复制到list//为了完成一个完整的拷贝,我们需要先给list赋值,大小和src一样ArrayList<String> list1 = new ArrayList<>();for (int i = 0; i < list.size(); i++) {list1.add("");}Collections.copy(list1,list);System.out.println(list1);//boolean replaceAll(list,"a","b")把list集合里的a替换为bCollections.replaceAll(list,"a","A");}
}
8.练习
1.
(1).创建 3个 Dog {name,age} 对象,放入到 ArrayList 中,赋给 List 引用
(2).用选代器和增强for循环两种方式来遍历
(3).重写Dog 的toString方法,输出name和age
public class e1 {public static void main(String[] args) {List<Object> Dog = new ArrayList<>();Dog.add(new Dog("小白",1));Dog.add(new Dog("小黑",2));Dog.add(new Dog("小红",3));Iterator iterator = Dog.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}for (Object dog :Dog) {System.out.println(dog);}}
}
class Dog{private String name;private int age;public Dog(String name, int age) {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;}@Overridepublic String toString() {return "姓名:"+this.name+" ,年龄:"+this.age;}
}
2.
public class a {public static void main(String[] args) {ArrayList<Object> book = new ArrayList<>();book.add(new Book("西游记", "吴承恩", 10));book.add(new Book("水浒传", "施耐庵", 19));book.add(new Book("红楼梦", "曹雪芹", 100));book.add(new Book("三国演", "罗贯中", 80));//book.add(new Book("西游记","吴承恩",10));int[] array = new int[book.size()];for (Object o : book) {System.out.println(o);}BubbleSort(book);for (Object o : book) {System.out.println(o);}}//静态方法public static void BubbleSort(List list) {// 外层循环控制冒泡排序的趟数// size-1表示:最后一趟区间中只剩余1个元素,该趟冒泡可以省略for (int i = 0; i < list.size() - 1; i++) {// 具体冒泡的方式:用相邻的两个元素进行比较,前一个大于后一个元素时,交换着两个数据,依次直到数组的末尾for (int j = 1; j < list.size() - i-1; j++) {//取出bookBook book1=(Book)list.get(j);Book book2=(Book)list.get(j+1);if (book1.getPrice()>book2.getPrice()) {list.set(j,book2);list.set(j+1,book1);}}}}
}
class Book{private String name;private int price;private String actor;public Book(String name, String actor,int price) {this.name = name;this.price = price;this.actor = actor;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getActor() {return actor;}public void setActor(String actor) {this.actor = actor;}@Overridepublic String toString() {return "名称"+name+"\t\t价格:"+price+"\t\t作者:"+actor;}
}
3.
ublic class e3 {public static void main(String[] args) {HashSet<Object> set = new HashSet<>();set.add(new Employee1("a",12));set.add(new Employee1("b",19));set.add(new Employee1("a",12));System.out.println(set);}
}
class Employee1 {private String name;private int age;//如果name'和age相同,返回相同的@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employee1 employee1 = (Employee1) o;return age == employee1.age && Objects.equals(name, employee1.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}public Employee1(String name, int age) {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;}@Overridepublic String toString() {return "Employee1{" +"name='" + name + '\'' +", age=" + age +'}';}
}
4.
public class e1 {public static void main(String[] args) {Set set = (Set) new HashSet();set.add(new Employee("1", 1000, new MyDate(2,2,2)) );set.add(new Employee("1", 1000, new MyDate(2,2,2) ));set.add(new Employee("2", 1000, new MyDate(2,2,2) ));System.out.println(set.toString());}
}
class Employee{private String name;private int sal;private MyDate birthday;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employee employee = (Employee) o;return Objects.equals(name, employee.name) && Objects.equals(birthday, employee.birthday);}@Overridepublic int hashCode() {return Objects.hash(name, birthday);}public Employee(String name, int sal, MyDate birthday) {this.name = name;this.sal = sal;this.birthday = birthday;}public MyDate getBirthday() {return birthday;}public void setBirthday(MyDate birthday) {this.birthday = birthday;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", sal=" + sal +", birthday=" + birthday +'}';}
}class MyDate{private int year;private int month;private int day;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;MyDate myDate = (MyDate) o;return year == myDate.year && month == myDate.month && day == myDate.day;}@Overridepublic int hashCode() {return Objects.hash(year, month, day);}public MyDate(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) {this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}@Overridepublic String toString() {return "MyDate{" +"year=" + year +", month=" + month +", day=" + day +'}';}}
5.
public class e4 {public static void main(String[] args) {LinkedHashSet<Object> set = new LinkedHashSet<>();set.add(new Car("qwq",123));set.add(new Car("qwq",123));set.add(new Car("奔驰",12223));System.out.println(set);}
}
class Car{private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(price, car.price) == 0 && Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}
5.
键:员工id
值:工对象
使用HashMap添加3个员工对象,要求
并遍历显示工资>18000的员工(遍历方式最少两种)
员工类: 姓名、工资、员工id
public class e5 {public static void main(String[] args) {HashMap<Object, Object> map = new HashMap<>();map.put("123456",new Emplyee("小明",12000,"123456"));map.put("123457",new Emplyee("小来",19000,"123457"));map.put("123458",new Emplyee("小张",1200,"123458"));Set<Object> objects = map.keySet();for (Object o :objects) {//先获取valueEmplyee e=(Emplyee) map.get(o);//根据键获取值,再转为empif (e.getSal()>18000)System.out.println(e);}//1.先获取entrySetSet<Map.Entry<Object, Object>> entries = map.entrySet();//2.创建enterset的迭代器Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();while (iterator.hasNext()) {//3.把迭代的内容转为Map.entryMap.Entry<Object, Object> next = (Map.Entry) iterator.next();//4.Map.entry通过getValue获取内容,再把内容转为EmplyeeEmplyee e1=(Emplyee) next.getValue();if (e1.getSal()>18000)System.out.println(e1);}}
}
class Emplyee{private String name;private int sal;private String id;public Emplyee(String name, int sal, String id) {this.name = name;this.sal = sal;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSal() {return sal;}public void setSal(int sal) {this.sal = sal;}public String getId() {return id;}public void setId(String id) {this.id = id;}@Overridepublic String toString() {return "Emplyee{" +"name='" + name + '\'' +", sal=" + sal +", id='" + id + '\'' +'}';}
}
6.
按要求实现:
(1)封装一个新闻类,包含标题和内容属性,提供get、set方法,重写toString方法,打印对象
时只打印标题;
(2) 只提供一个带参数的构造器,实例化对象时,只初始化标题; 并且实例化两个对象:
新闻一: 新冠确诊病例超千万,数百万印度教信徒赴恒河“圣浴”引民众担忧
新闻二:男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生
(3)将新闻对象添加到ArrayList集合中,并且进行倒序遍历;
(4)在遍历集合过程中,对新闻标题进行处理,超过15字的只保留前15个,然后在后边加
(5) 在控制台打印遍历出经过处理的新闻标题
public class e1 {public static void main(String[] args) {ArrayList list=new ArrayList<>();list.add(new News("新闻一:新冠确诊qwqwq,并且实例化两个对象qwqwqq"));list.add(new News("新闻二:突然想起来2个月前的鱼还在与哇嘎里aaaaaa"));Collections.reverse(list);for (Object o :list) {News n=(News) o;System.out.println(processTitle(n.getTitle()));}}public static String processTitle(String title) {if (title==null){return "";}if(title.length()>15){return title.substring(0,15)+"...";//(0,15]}else {return title;}}
}class News{private String title;private String content;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "News{" +"title='" + title +'}';}public News(String title) {this.title = title;}
}
7.
按要求完成下列任务
1)使用HashMap类实例化一个Map类型的对象m,键 (String) 和值 (int)分别用于存储员
工的姓名和工资,存入数据如下:jack-650元; tom-1200元; smith-2900元;
2)将iack的工资更改为2600元,为所有员工工资加薪100元;
3)遍历集合中所有的员工
4)遍历集合中所有的工资
public class e3 {public static void main(String[] args) {HashMap<Object, Object> map = new HashMap<>();map.put("jack",650);map.put("tom",1200);map.put("smith",2900);map.replace("jack",2600);//薪资加100Set keyset=map.keySet();for (Object o :keyset) {map.put(o,(Integer)map.get(o)+100);}System.out.println(map);//遍历Set<Map.Entry<Object, Object>> entries = map.entrySet();Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<Object, Object> next = iterator.next();System.out.println(next.getKey()+"="+next.getValue());}//遍历工资Collection<Object> values = map.values();for (Object o :values) {System.out.println(o);}}
}
8.
试分析HashSet和TreeSet分别如何实现去重的?
(1)HashSet的去重机制:
- hashCode()+ equals(),底层先通过存入对象,进行运算得到一个hash值,
- 通过hash值得到对应的索引,
- 如果发现table索引所在的位置,没有数据,就直接存放
- 如果有数据,就进行equals比较[遍历比较],
- 如果比较后,不相同,就加入,否则就不加入.
(2) TreeSet的去重机制:
- 如果你传入了一个Comparator匿名对象,就使用实现的compare去重。
- 如果方法返回0,就认为是相同的元素/数据,就不添加。
- 如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Compareable接口的compareTo去重。(字符串的compaterto方法比较的是内容)