Java集合框架
泛型
- 泛型:指的是“泛指的类型”,将数据类型参数化。在类与类,类与接口,方法之间进行传递,类似于“传参”。
- 泛型在类中的使用:使用这个类时,需指定泛型的类型,如果不指定,默认为Object
//定义泛型类
class Animal<T>{}
class Animal<T,M>{}
//声明引用
Animal<String> animal;
//实例化对象
Animal<Integer> animal = new Animal<>();
//访问静态成员
Animal<Integer>.dispaly();
//被继承
class Dog extends Animal<String>{}
class Dog<T> extends Animal<T>{}
package geninclass;
public class Person<T> {
String name;
int age;
T role;
}
class Student extends Person<String>{
}
class Teacher<E> extends Person<E>{
}
class Test{
public static void main(String[] args) {
Student stu = new Student();
stu.role = "学生";//只能赋值字符串
System.out.println(stu.role);
Teacher<String> teacher = new Teacher<>();
teacher.role ="老师";
System.out.println(teacher.role);
//泛型不确定,默认值为Object
Teacher teacher1 = new Teacher();
teacher1.role = 12;
System.out.println(teacher1.role);
}
}
- 泛型在接口中的使用:使用这个接口时,需指定泛型的类型,如果不指定,默认为Object
//定义接口
Interface MyInterface<T>{}
Interface MyInterface<T,M>{}
//类实现接口
class MyInterfaceImp implements MyInterface<String>{}
//接口访问接口中的静态成员
Myinterface<String>.name;
//接口继承接口
Interface SubMyInterface extends MyInterface<String>{}
package genininterface;
public class MyInterfaceImp implements MyInterface<MyClass> {
@Override
public void compare(MyClass t1, MyClass t2) {
System.out.println(t1.age - t2.age);
}
}
interface MyInterface<T>{
void compare(T t1,T t2);
}
class MyClass{
int age;
}
//接口继承接口
interface MyInterface1 extends MyInterface<MyClass>{}
class Test{
public static void main(String[] args) {
//方法一:实现接口
MyInterfaceImp myInterfaceImp = new MyInterfaceImp();
MyClass my1 = new MyClass();
MyClass my2 = new MyClass();
my1.age = 20;
my2.age = 10;
myInterfaceImp.compare(my1,my2);
//方法二:实现接口
MyInterface<MyClass> myInterface = new MyInterface<MyClass>(){
@Override
public void compare(MyClass t1, MyClass t2) {
System.out.println(t1.age-t2.age);
}
};
myInterface.compare(my1,my2);
//方法三:实现接口
MyInterface<MyClass> myInterface1 = (t1,t2)-> System.out.println(t1.age-t2.age);
myInterface1.compare(my1,my2);
}
}
- 泛型在方法中的使用:泛型在方法返回值前面定义
package geninmethod;
public class Test<T>{
//情况一:方法中的泛型就是类中的泛型
public void display(T t){
System.out.println(t);
}
//情况二:方法中的泛型是自己使用的泛型,与类中泛型无关,表示方法的参数为任意类型
public <T> void show(T t){
System.out.println(t);
}
//情况三:方法中的泛型是自己使用的泛型,与类中泛型无关,表示方法的参数为任意类型
//静态方法定义泛型时,只能这样定义
public static <T>void fun(T t){
System.out.println(t);
}
public static void main(String[] args) {
Test<String> test = new Test<>();
test.display("scdhd");
test.show(12);
Test.fun(22);
}
}
集合
-
集合:是一个数据容器,用来存储引用数据类型的数据
-
集合和数组的区别
-
存储的数据类型:
- 数组可以存储基本数据类型和引用数据类型
- 集合只能存储引用数据类型,基本数据类型需要装箱,才能存入集合中
-
长度
- 数组的长度固定。不能动态添加
- 集合是变长的容器,长度可以改变,即集合中可以随时添加、删除元素
-
元素操作
- 数组只能通过下标对元素访问,如果进行类似于排序的操作,需要自己写算法实现
- 集合中封装类若干对元素进行操作的方法,直接使用集合比较方便
-
-
Collection集合:是单列集合的顶级接口,在这种集合中存储的数据,只占一列,所有的元素,直接存储于各种数据结构中。Collection集合没有下标的概念。
-
集合常用方法:
//声明集合 Collection<String>collection = new Arraylist<>(); Collection<String>collection1 = new Arraylist<>(); //添加单个元素 collection.add("sdds") //添加集合元素 collection1.add("sidss"); collection1.add("dsss"); collection.addAll(collection1);//collection中元素个数为3 //删除指定元素 collection.remove("sdds"); //以集合的形式删除元素 collection.removeAll(collection1); //删除满足条件的元素 collection1.removeIf(ele->ele.matches("L.*"));//删除以L开头的元素 //保留元素 collection.retainAll(collection1); //清空集合 collection.clear(); //判断集合是否包含指定元素 boolean flag = collection.contain("sdds"); //判断集合是否包含集合中的元素 boolean flag = collection.containAll(collection1); //获取元素的大小 int size = collection.size(); //判断元素是否为空 boolean flag = collection.isEmpty(); //集合转换为数组 Object[] objects = collection.toArray(); //集合转换为指定类型的数组 String[] strings = collection.toArray(new String[4]);
-
集合的遍历方法:
-
增强for循环
-
迭代器
Iterator<String> iterator = collection.iterator();//获取迭代器 while(iterator.hasNext()){ System.out.println(iterator.next()); }
-
foreach()
collection.foreach(ele-> System.out.println(ele))
-
-
List集合:是Collection的子接口,具有Collection的所有方法,同时围绕下标有些独有方法
//声明List集合 List<String> list = new ArrayList<>(); //添加元素 list.add("sdsvdu"); list.add("sdsvd"); //在指定位置添加元素 list.add(1,"fsdsd"); //在指定位置添加集合中的元素 list.addAll(1,list); //删除指定位置元素 list.remove(1); //修改指定位置元素 list.set(2,"dfyed"); //替换元素 list.replaceAll(ele->ele.concat("aa"));//将集合中的每一个元素后添加aa,然后替换每个元素 //获取指定位置元素 list.get(2); //获取指定元素下标 int index = list.indexof("dfyedaa")//获取该元素的第一个位置 int index = list.lastIndexof("dfyedaa")//获取该元素的最后一个位置 //截取集合 List<String> list1 = list.subList(1,3);
- List集合排序
package collection; import java.util.ArrayList; import java.util.List; //对List集合进行排序 public class UseList { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("asssss"); list.add("ass"); list.add("asss"); list.sort((e1,e2)->e1.length()-e2.length());//按长度的从小到大排序,e2-e1:从大到小 list.forEach(ele-> System.out.println(ele)); } }
-
除了Collection的三种方法外,还有使用下标的方式
for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); }
迭代器方法:iterator()->只能删除元素,listIterator():可以添加、修改、删除元素,是List特有的
List<Integer> list1 = new ArrayList<>(); Collections.addAll(list1,10,20,30,40); ListIterator<Integer> listIterator = list1.listIterator(); while(listIterator.hasNext()){ //可以进行一些增删改查操作 Integer num = listIterator.next(); System.out.println(num); }
-
-
ArrayList集合和LinkedList集合
-
相同点:
- 都是List集合中常用的集合类x
- 对集合中的元素操作的方法基本一致
-
不同点:
- ArrayList底层实现的是数组,适用于元素查找
- LinkedList底层实现的是双链表,适用于元素增删
linkList.pop();//弹出列表中的第一个元素 linkList.push();//添加位置为列表的头结点
-
List集合中的元素有序(输出的元素按照添加的顺序),并且元素可以重复
-
-
Set集合:Set接口继承自Collection接口
-
Set集合是去重复的集合,不允许重复的元素出现。另外,数据的存储时无序的(添加顺序和存储顺序不一致)并且没有下标的概念。
-
HashSet是Set实现类:存储方式为哈希表(先算哈希值,哈希值除以数组长度得到余数,在余数对应的数组中的元素处创建链表存储)。元素存储过程中,先比较哈希值(hashCode()),如果有相同的,则进行equals比较,若相等,该元素添加失败。保证了集合中元素的不可重复性。
Hashset实现元素不可重复性:重写hashCode()和equals()方法
User类:
package collection; import java.util.Objects; public class User { private String name; private int age; public User(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; } //重写hashCode方法 @Override public int hashCode() { //以姓名和年龄获取哈希值,若相等,则哈希值相等 return Objects.hash(name, age); } //比较内容 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || this.getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && Objects.equals(name, user.name); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package collection; //HashSet实现数据的不可重复性 import java.util.Collections; import java.util.HashSet; public class UseHashSet { public static void main(String[] args) { HashSet<User> hashSet = new HashSet<>(); User user1 = new User("sss",12); User user2 = new User("ss",13); User user3 = new User("ee",14); User user4 = new User("s3",15); User user5 = new User("s3",15); Collections.addAll(hashSet,user1,user2,user3,user4); System.out.println(hashSet); } }
-
TreeSet:Set接口的实现类,底层实现是二叉树,该集合可以对元素进行去重和自动升序处理。
Person类:
package collection; public class Person implements Comparable<Person>{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public String getName() { return name; } //对集合中的元素升序:继承Comparable接口,并实现compareTo()方法 @Override public int compareTo(Person o) { return this.age-o.age; }x @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package collection; import java.util.Collections; import java.util.TreeSet; //TreeSet使用 public class UseTreeSet { public static void main(String[] args) { TreeSet<Person> treeSet = new TreeSet<>(); Person person1 = new Person("ssd",12); Person person2 = new Person("ssd3",18); Person person3 = new Person("ssd2",13); //年龄若相同,则视为相同元素,不能添加到集合中 Person person4 = new Person("ssd5",13); Collections.addAll(treeSet,person1,person2,person3,person4); System.out.println(treeSet); } }
-
String类型的字符串的排序方式是按照字符串大小排序,如果想要按照字符串长度排序,需要借助Comparator接口中的compare()方法实现
package collection; import java.util.Collections; import java.util.TreeSet; public class UseComparator { public static void main(String[] args) { //字符串按照长度排序 TreeSet<String> treeSet = new TreeSet<>((t1,t2)->{return t1.length()-t2.length();}); Collections.addAll(treeSet,"sdfsd","sd","wdwfgeuf","z"); System.out.println(treeSet); //Person类按照名字排序 TreeSet<Person> treeSet1 = new TreeSet<>((t1,t2)->{return t1.getName().compareTo(t2.getName());}); Person person1 = new Person("ssdwew",12); Person person2 = new Person("qsd3ew",18); Person person3 = new Person("asd2wew",13); Collections.addAll(treeSet1,person1,person2,person3); System.out.println(treeSet1); } }
-
-
Map集合:双列集合的顶级接口,没有继承Collection接口,在Map集合中存储的是键值对。由于没有实现Iterable接口,因此该集合不能使用增强for循环遍历。
-
常用方法:
package map; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class UseMethod { public static void main(String[] args) { //声明Map集合 Map<String,String> map =new HashMap<>(); //添加元素,返回值value为上次添加的键值相同的对应的值 String value = map.put("name","sdd"); //添加的元素的键在集合中已经存在,则覆盖集合中的键值 String val = map.put("name","sdds"); System.out.println(map); //添加的元素的键在集合中已经存在,则添加失败 String va = map.putIfAbsent("name","avudcyd"); System.out.println(map); map.put("address","nanjing"); //移除元素 map.remove("name"); map.remove("name","sdds"); //清空集合 //map.clear(); //替换元素方式一 String res = map.replace("address","beijing");//返回值为被替换的值 //替换元素方式二 boolean flag = map.replace("address","beijing","shanghai");//替换成功,返回true //替换元素方式三:实现BiFunction接口的apply(T t,U u)方法,t->键,u->值 map.replaceAll((t,u)->{ if(t.equals("address")){ return "nanjing"; } return u; }); System.out.println(map); //根据键获取值 String values = map.get("address"); System.out.println(values); //如果键值在集合中不存在,则使用默认值。如果存在,默认值失效 String height = map.getOrDefault("height","40"); //size()->集合长度 isEmpty()->是否为空。 //containsKey()->是否存在某键,containsValue()->是否存在某个值 //获取map集合中的所有值 Collection<String> valus = map.values(); valus.forEach(ele-> System.out.println(ele)); } }
-
遍历Map集合
-
使用KeySet()方法:获取集合中的所有键值,通过键值获取值
-
forEach():借助BiConsumer函数接口,重写accept(T t,O o)方法
-
使用entrySet()方法,将Map集合中的键值对转换为Map.Entry<Key,Value>
package map; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapTraverse { public static void main(String[] args) { //声明Map集合 Map<String,String> map = new HashMap<>(); //集合中添加元素 map.put("name","dwdd"); map.put("address","nanjing"); //遍历方法一:KeySet方法遍历Map集合 Set<String> set = map.keySet(); set.forEach((key)-> System.out.println("value:"+map.get(key))); //遍历方法二:forEach():借助BiConsumer函数接口,重写accept(T t,O o)方法 map.forEach((key,value)-> System.out.println(key+":"+value)); //遍历方法三: Set<Map.Entry<String,String>> set1 = map.entrySet(); for (Map.Entry<String, String> entry : set1) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key+":"+value); } } }
-
-
HashMap和TreeMap:集合元素无序,保证键值不重复。
-
HashMap和HashTable的区别:
- HashMap是线程不安全的集合,HashTable是线程安全的集合
- HashMap允许出现null键值,HashTable是不允许的
- HashMap的父类是AbstractMap,HashTable的父类是Dictionary
- HashMap底层算法效率优于HashTable
-
LinkedHashMap类似于LinkedHashSet,保证元素的有序性
-
-
Cllection工具类的使用
package collection; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class UseCollectionMethod { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); Collections.addAll(list,10,24,20,15,30,9); //获取list集合中的最大值 Integer max = Collections.max(list); System.out.println("max:"+max); //自定义获取最大值方法 Integer max1 = Collections.max(list,(num1,num2)-> {return num2-num1;}); //最小值min()使用方法与max()相同 //打乱list集合中的数据 Collections.shuffle(list); System.out.println(list); //交换list集合中的元素位置 Collections.swap(list,0,1); System.out.println(list); //翻转list集合中的元素 Collections.reverse(list); System.out.println(list); //list集合元素排序 Collections.sort(list); System.out.println(list); //自定义list集合元素排序方式 Collections.sort(list,(num1,num2)->num2-num1); System.out.println(list); //复制元素到指定集合中 List<Integer> list1 = new ArrayList<>(); Collections.addAll(list1,0,0,0,0,0,0); Collections.copy(list1,list); System.out.println(list1); //填充元素 Collections.fill(list,6); System.out.println(list); } }