目录
1. Hashtable
基本上很少使用
- Hashtable是个古老的 Map 实现类。Hashtable是线程安全的。
- Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
- Hashtable 不允许使用 null作为 key 和 value
- Hashtable无序性
- 判断相等与HashMap相同
- 语法:
Hashtable map = new Hashtable();
2. Properties
- Properties 类是 Hashtable 的子类,该对象用于处理属性文件
- 由于属性文件里的 key、 value 都是字符串类型,所以 Properties 里的 key和 value 都是字符串类型
- 存取数据时,建议使用
setProperty(String key,String value)
方法和getProperty(String key)
方法
先创建一个文件jdbc.properties
输入以下内容:
username=root
password=root
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driver=com.mysql.driver.Driver
进行测试
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
FileInputStream in = new FileInputStream("jdbc.properties");
properties.load(in);
System.out.println(properties.getProperty("username"));
System.out.println(properties.getProperty("password"));
System.out.println(properties.getProperty("jdbc.url"));
System.out.println(properties.getProperty("jdbc.driver"));
}
}
root
root
jdbc:mysql://localhost:3306/test
com.mysql.driver.Driver
3. Collections工具类
- Collections 是一个操作
Set、 List 和 Map
等集合的工具类 - Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
3.1 具体方法
- 排序操作: (均为static方法)
reverse(List)
: 反转 List 中元素的顺序shuffle(List)
: 对 List 集合元素进行随机排序(洗牌)sort(List)
: 根据元素的自然顺序对指定 List 集合元素按升序排序sort(List, Comparator)
: 根据指定的 Comparator 产生的顺序对 List 集合元素进行排序swap(List, int, int)
: 将指定 list 集合中的 i 处元素和 j 处元素进行交换
- 查找、替换
Object max(Collection)
: 根据元素的自然顺序,返回给定集合中的最大元素Object max(Collection, Comparator)
:根据 Comparator 指定的顺序,返回给定集合中的最大元素Object min(Collection)
根据元素的自然顺序,返回给定集合中的最小元素Object min(Collection, Comparator)
根据 Comparator 指定的顺序,返回给定集合中的最小元素int frequency(Collection, Object)
: 返回指定集合中指定元素的出现次数void copy(List dest,List src)
:将src中的内容复制到dest中boolean replaceAll(List list, Object oldVal, Object newVal)
: 使用新值替换List 对象的所有旧值
synchronizedXxx()
方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
public class CollectionsDemo {
public static void main(String[] args) {
List list = new ArrayList();
List list2 = new ArrayList();
list2.add("111");
list.add("xxx");
list.add("yyy");
list.add("nnn");
list.add("aaa");
list.add("aaa");
list.add("111");
list.add("222");
list.add("333");
System.out.println("原初list=" + list);
//反转reverse(List)
Collections.reverse(list);
System.out.println("反转list=" + list);
//洗牌(随即存放)shuffle(List)
Collections.shuffle(list);
System.out.println("洗牌list=" + list);
//自然排序sort(List),类型必须相同,从小到大
Collections.sort(list);
System.out.println("自然排序" + list);
//定制排序sort(List ,Comparator)从大到小
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
return -s1.compareTo(s2);
}
};
Collections.sort(list, com);
System.out.println("定制排序" + list);
//交换swap(List, int ,int)
Collections.swap(list, 0, 1);
System.out.println("交换list=" + list);
//给定集合中极值元素根据自然排序
System.out.println("自然排序最大:" + Collections.max(list));
System.out.println("自然排序最小:" + Collections.min(list));
//给定集合中最大元素根据定制排序
System.out.println("定制排序最大" + Collections.max(list,com));
System.out.println("定制排序最小" + Collections.min(list,com));
//返回集合中指定元素出现次数
System.out.println("aaa出现的次数" + Collections.frequency(list, "aaa"));
//复制类型,copy(List list,List list2) 即:list = list2;
// Collections.copy(list2,list);目标列表的大小必须大于源列表的大小
// System.out.println(list2);
//将List集合上锁
List syncList = Collections.synchronizedList(list); //返回线程安全的集合
syncList.add("666");//添加元素线程安全
}
}
运行结果
原初list=[xxx, yyy, nnn, aaa, aaa, 111, 222, 333]
反转list=[333, 222, 111, aaa, aaa, nnn, yyy, xxx]
洗牌list=[aaa, 222, 111, aaa, nnn, yyy, xxx, 333]
自然排序[111, 222, 333, aaa, aaa, nnn, xxx, yyy]
定制排序[yyy, xxx, nnn, aaa, aaa, 333, 222, 111]
交换list=[xxx, yyy, nnn, aaa, aaa, 333, 222, 111]
自然排序最大:yyy
自然排序最小:111
定制排序最大111
定制排序最小yyy
aaa出现的次数2
4. 泛型
泛型就像是标签,就是允许在定义类、 接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。
- 从JDK1.5以后, Java引入了“参数化类型( Parameterized type)的概念,允许我们在创建集合时再指定集合元素的类型, 正如: List, 这表明该List只能保存字符串类型的对象。
- JDK1.5改写了集合框架中的全部接口和类, 为这些接口、 类增加了泛型支持,从而可以在声明集合变量、 创建集合对象时传入类型实参。
- 集合没有泛型时:读取出数据需要强制类型转换,有可能抛出ClassCastException
- 集合中使用泛型:可以避免强转,避免抛出ClassCastException
4.1 List泛型
public class Genericity {
public static void main(String[] args) {
List<String> list = new ArrayList<>(10);
list.add("123");
list.add("234");
list.add("345");
System.out.println(list.get(1));
System.out.println("================");
//迭代器循环
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("================");
//增强for循环
for (String s : list) {
System.out.println(s);
}
}
234
================
123
234
345
================
123
234
345
4.2 Map泛型
@Test
public void teat() {
Map map = new HashMap();
map.put("a", 111);
map.put(222, "b");
map.put(new Date(), "ccc");
Set set = map.entrySet();
//EntrySet
for (Object o : set) {
Map.Entry entry = (Map.Entry) o;
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("================");
//keySet
for (Object o : map.keySet()) {
System.out.println(o + " " + map.get(o));
}
}
@Test
public void test2(){
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("a", 1);
map.put("b", 1);
map.put("c", 1);
map.put("d", 1);
map.put("e", 1);
map.put("f", 1);
map.put("g", 1);
map.put("h", 1);
//EntrySet
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("================");
//keySet
for (String s : map.keySet()) {
System.out.println(s + " " + map.get(s));
}
System.out.println("================");
//iterator
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s + " " + map.get(s));
}
}
5. 自定义泛型
5.1 泛型类
在类声明时使用泛型约束这个类
语法:public class 类名 <泛型类型> {}
class GenericsCls<T1,T2>{
private T1 t1;
private T2 t2;
public GenericsCls() {
}
public GenericsCls(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
}
public void setT1(T1 t1) {
this.t1 = t1;
}
public T1 getT1() {
return t1;
}
public T2 getT2() {
return t2;
}
public void setT2(T2 t2) {
this.t2 = t2;
}
public void getT(){
System.out.println(this.t1);
System.out.println(this.t2);
}
}
public static void main(String[] args) {
GenericsCls<String, Integer> gen = new GenericsCls<>("abc",114514);
gen.getT();
GenericsCls<String, Date> bean = new GenericsCls<>("t1 = 1",(new Date()));
bean.getT();
bean.setT1("t1 = 1");
bean.setT2(new Date());
System.out.println(bean.getT1());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(sdf.format(bean.getT2()));
}
abc
114514
t1 = 1
Thu Aug 10 19:33:58 CST 2023
t1 = 1
2023-08-10
5.2 泛型方法
语法:public <泛型类型> 返回类型 方法名(泛型类型 变量名) {}
修饰符 静态 定义类型 返回类型 方法名 形参
public static <T1> T1 test (T1 t1){
System.out.println(t1);
return t1;
}
public static void main(String[] args) {
String str = test("abc");
Date date = test(new Date());
Integer i = test(123);
}
abc
Thu Aug 10 19:36:49 CST 2023
123
5.3 泛型接口
语法:interface 接口名 <T>{}
实现类语法:class 类名 implements 接口名 <String> {}
此时接口中的T为String类型
interface GenricsInterface<T>{
T getValue(T t);
}
class IntegerImpl implements GenricsInterface<Integer> {
@Override
public Integer getValue(Integer integer) {
return integer;
}
}
class StringImpl implements GenricsInterface<String> {
@Override
public String getValue(String s) {
return s;
}
}
public static void main(String[] args) {
IntegerImpl integer1 = new IntegerImpl();
System.out.println(integer1.getValue(114515));
StringImpl string1 = new StringImpl();
System.out.println(string1.getValue("yu_yang"));
}
114515
yu_yang
6. 泛型通配符
6.1 通配符的上边界
<? extends T>
,在类型参数中使用 extends 表示这个泛型中的参数必须是 T 或者 T 的子类
语法:public static void f1(List<? extends Father> list) {}
传入的参数为一个list集合,该集合存放的元素为Father或其子类类型
public class WildCard {
public static void f1(List<? extends Father> list) {//通配符的上界 只允许Father和其子类
}
@Test
public void test1() {
List<GrandFather> grandFatherList = new ArrayList<>();//四种泛型的list
List<Father> fatherList = new ArrayList<>();
List<Mother> motherList = new ArrayList<>();
List<Son> sonList = new ArrayList<>();
// f1(grandFatherList);
f1(fatherList);
f1(sonList);
// f1(motherList);
}
剩下的两个报错,因为它们不是Father或其子类
6.2 通配符的下边界
? super Father
:Father和father的父类
语法:public static void f1(List<? super Father> list) {}
传入的参数为一个list集合,该集合存放的元素为Father或其父类类型
public class WildCard {
public static void f2(List<? super Father> list) {//通配符的下界,只允许Father和其父类
}
@Test
public void test1() {
List<GrandFather> grandFatherList = new ArrayList<>();//四种泛型的list
List<Father> fatherList = new ArrayList<>();
List<Mother> motherList = new ArrayList<>();
List<Son> sonList = new ArrayList<>();
f2(grandFatherList);
f2(fatherList);
// f2(sonList);
// f2(motherList);
}
剩下的两个报错,因为它们不是Father或其父类
6.3 泛型边界在接口中的应用
声明接口的泛型只能使用T extends Type
interface GenricsInterface<T extends Father> {
public T getValue();
}
class Impl1 implements GenricsInterface<Father> {//必须为Father类或其子类
@Override
public Father getValue() {
return null;
}
}
class Impl5 implements GenricsInterface<Son> {
@Override
public Son getValue() {
return null;
}
}
6.4 无界通配符
不常用
?表示传入任意类型
public static void f2(List<?> list) {
}
public void test1() {
f2(sonList);
f2(daughterList);
f2(fatherList);
f2(grandFatherList);
f2(motherList);
f2(new ArrayList<String>());
}
编译都能通过
7.泛型的擦除
Java的泛型是伪泛型,因为在编译后,所有的泛型信息都会被擦除掉,我们常称为泛型擦除。
比如:
@Test
public void test1() {
List<String> stringList = new ArrayList<String>(); //ArrayList<String>.class
stringList.add("泛型");
List<Integer> integerList = new ArrayList<Integer>(); //ArrayList.class
integerList.add(1);
System.out.println(stringList.getClass());
System.out.println(stringList.getClass() == integerList.getClass()); //true
}
运行结果
class java.util.ArrayList
true
虽然两种集合使用不同的泛型,但运行时他们的类型是相同的