Java编程问题top100---基础语法系列(三)
- 十一、在java中如何对比(compare)string
- 补充说明
- 十二、Map<Key,Value>基于Value值排序
- 方法1:使用TreeMap
- 方法2:
- 十三、HashMap和Hashtable的区别
- 十四、如何便捷地将两个数组合到一起
- 工具类一行代码搞定
- 不借助依赖包
- 非泛型
- 泛型
- 十五、Java 是否支持默认的参数值
- 创建者模式
- 方法(构造函数)重载
- null 的传递
- 多参数方式
- 使用 Map 作为方法中的参数
- Java编程问题top100---基础语法系列导航
别光看,动手敲一下代码,运行一下
虽然敲代码有人苦有人乐在其中,祝你开开心心找到那种写完代码成功无bug的乐趣,或者修改bug成功的那种满足感
十一、在java中如何对比(compare)string
==
对应的是指针相等,也就是他们是否为同一个对象.equals()
对应的是值相等,也就是逻辑相等
因此,如果你想检查两个字符串是否为相同值,那么应该用.equals()
方法
// 在java中如何对比(compare)string
public class Test01 {public static void main(String[] args) {// 值是相等的boolean result01 = new String("test").equals("test");System.out.println("new String(\"test\").equals(\"test\"): "+result01);// ... 值相等,但不是同个对象(指向不同的地址空间)boolean result02 = new String("test") == "test";System.out.println("new String(\"test\") == \"test\": "+ result02);// ... 同上boolean result03 = new String("test") == new String("test");System.out.println("new String(\"test\") == new String(\"test\"): "+result03);// 这个返回true,是因为这种写法属于字符串字面量,编译器会维护一个常量池,相同的字面量,都会指向相同的一个对象boolean result04 = "test" == "test";System.out.println("test == test :" + result04);}
}
输出结果如下:
new String("test").equals("test"): true
new String("test") == "test": false
new String("test") == new String("test"): false
test == test :true
因此, 值的对比,一般都是用equals方法。字符串字面量之间的对比,也可以用==
下面再举个字符串字面量的例子,下面代码中,前四个对比,返回true,最后一个返回false。
public static final String test1 = "test";public static final String test2 = "test";@Testpublic void test() {String test3 = "test";String test = "test";System.out.println(test3.equals(test));System.out.println(test3 == test);System.out.println(test1.equals(test2));System.out.println(test1 == test2);System.out.println(test1 == new String("test"));}
补充说明
- 如果你重写了equal方法,就应该修改对应的hashcode方法,否则将会违反这两个方法的对等关系。
如果两个对象是相等(equal)的,那么两个对象调用hashCode()方法必须产生相同的整数结果,即:
equal为true,hashCode也必须为true,equal为false,hashCode也必须为false - 如果要忽略大小写进行对比,可以用equalsIgnoreCase()方法
十二、Map<Key,Value>基于Value值排序
方法1:使用TreeMap
可以参考下面的代码
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;// Map<Key,Value>基于Value值排序
public class Test02 {// 方法1:使用TreeMappublic static void main(String[] args) {HashMap<String, Double> map = new HashMap<String, Double>();ValueComparator bvc = new ValueComparator(map);TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);map.put("A", 99.5);map.put("B", 67.4);map.put("C", 67.4);map.put("D", 67.3);System.out.println("unsorted map: " + map);sorted_map.putAll(map);System.out.println("results: " + sorted_map);}
}
package day03;import java.util.Comparator;
import java.util.Map;class ValueComparator implements Comparator<String> {Map<String, Double> base;public ValueComparator(Map<String, Double> base) {this.base = base;}// 注意:这个compare比较器施加的顺序与等号不一致。public int compare(String a, String b) {if (base.get(a) >= base.get(b)) {return -1;} else {return 1;}// 返回0将合并键}
}
译注:如果不自己写Comparator,treemap默认是用key来排序
方法2:
先通过linkedlist排好序,再放到LinkedHashMap中
import java.util.*;public class MapUtil {public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {List<Map.Entry<K, V>> list =new LinkedList<Map.Entry<K, V>>(map.entrySet());Collections.sort(list, new Comparator<Map.Entry<K, V>>() {public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {return (o1.getValue()).compareTo(o2.getValue());}});Map<K, V> result = new LinkedHashMap<K, V>();for (Map.Entry<K, V> entry : list) {result.put(entry.getKey(), entry.getValue());}return result;}
}
译注:如果map的size在十万级别以上,两者的耗时都是几百毫秒,第二个方法会快一些。否则,第一个方法快一些。如果你处理的map,都是几十万级别以下的大小,两种方式随意
十三、HashMap和Hashtable的区别
问题
在Java中HashMap和Hashtable的区别?
哪一个对于多线程应用程序更好?
回答:
HashMap和Hashtable的区别,HashMap和ConcurrentHashMap的区别
点链接,看第一点就是了
十四、如何便捷地将两个数组合到一起
工具类一行代码搞定
ArrayUtils.addAll(T[], T...)
(工具类要引入maven依赖来着,上个系列有提过)
代码:
import org.apache.commons.lang3.ArrayUtils;
import java.util.Arrays;
public class Test03 {public static void main(String[] args) {String[] first = {"I ", "am ", "the ", "first "};String[] second = {"I ", "am ", "second"};String[] both = ArrayUtils.addAll(first, second);System.out.println(Arrays.toString(both));}
}
不借助依赖包
非泛型
把下面的Apple
替换成你自己的类名
考虑到有新手可能不会写,贴个Apple类,其实只需要写好属性,getter和setter方法还有toString()方法什么的都是能一键生成的。
pom.xml
里导入lombok依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency>
@Getter@Setter
@AllArgsConstructor
@ToString
public class Apple {private String color;private int count;
}
Apple类可以直接贴个lombok的注解简单省事,下面是详细代码
public class Apple {private String color;private int count;public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}@Overridepublic String toString() {return "Apple{" +"color='" + color + '\'' +", count='" + count + '\'' +'}';}public Apple(String color, int count) {this.color = color;this.count = count;}
}
import java.util.Arrays;public class Test04 {public static void main(String[] args) {test01();}public static Apple[] concat(Apple[] first, Apple[] second) {int firstLen = first.length;int secondLen = second.length;Apple[] c = new Apple[firstLen + secondLen];System.arraycopy(first, 0, c, 0, firstLen);System.arraycopy(second, 0, c, firstLen, secondLen);return c;}public static void test01(){Apple first1 = new Apple("red",1);Apple second1 = new Apple("yellow", 2);Apple[] first = new Apple[]{first1,second1};Apple first2 = new Apple("red",3);Apple second2 = new Apple("yellow", 4);Apple[] second = new Apple[]{first2,second2};Apple[] three = concat(first,second);System.out.println(Arrays.toString(three));}
}
泛型
public static <T> T[] concatenate(T[] first, T[] second) {int firstLen = first.length;int secondLen = second.length;@SuppressWarnings("unchecked")T[] c = (T[]) Array.newInstance(first.getClass().getComponentType(), firstLen + secondLen);System.arraycopy(first, 0, c, 0, firstLen);System.arraycopy(second, 0, c, firstLen, secondLen);return c;}public static void test02() {//省略......跟test01()前面一样的内容Apple[] three = concatenate(first, second);System.out.println(Arrays.toString(three));}
注意,泛型的方案不适用于基本数据类型(int,boolean……)
十五、Java 是否支持默认的参数值
问:
在c++
中,常见到如下的方法定义(param3 默认为 false):
void MyParameterizedFunction(String param1, int param2, bool param3=false);
那在java中,是否也支持这样的定义方式?
答:
答案是否定的,不过我们可以通过多种方式处理这种参数默认值的情况。
创建者模式
要了解创建者模式的点这个,比较详细
使用创建者模式,你可以设定部分参数是有默认值,部分参数是可选的。如:
pom.xml里导入lombok依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency>
@Getter@Setter
@AllArgsConstructor
@ToString
@Builder
public class Apple {private String color;private int count;
}
Apple类可以直接贴个lombok的注解@Builder简单省事,这里贴详细的代码
public class Apple {private String color;private int count;Apple(String color, int count) {this.color = color;this.count = count;}public static AppleBuilder builder() {return new AppleBuilder();}public String getColor() {return this.color;}public int getCount() {return this.count;}public void setColor(String color) {this.color = color;}public void setCount(int count) {this.count = count;}public String toString() {return "Apple(color=" + this.getColor() + ", count=" + this.getCount() + ")";}public static class AppleBuilder {private String color;private int count;AppleBuilder() {}public AppleBuilder color(String color) {this.color = color;return this;}public AppleBuilder count(int count) {this.count = count;return this;}public Apple build() {return new Apple(this.color, this.count);}public String toString() {return "Apple.AppleBuilder(color=" + this.color + ", count=" + this.count + ")";}}
}
public class Test05 {public static void main(String[] args) {Apple a1 = new Apple.AppleBuilder().color("Eli").build();Apple a2 = new Apple.AppleBuilder().color("red").count(1).build();Apple a3 = new Apple.AppleBuilder().count(1).build();System.out.println(a1);System.out.println(a2);System.out.println(a3);}
}
输出
Apple(color=Eli, count=0)
Apple(color=red, count=1)
Apple(color=null, count=1)
方法(构造函数)重载
用构造函数举例:
public Apple(String color, int count) {this.color = color;this.count = count;}public Apple(String color) {this.color = color;}Apple apple1 = new Apple("a", 2);
Apple apple2 = new Apple("a");
构造函数重载,对于参数比较少的情况下,比较适合;当参数相对多的时候,可以考虑使用静态工厂方法,或添加一个参数辅助对象。
如果是常规方法重载,可以考虑使用 参数辅助对象,或者重命名多种情况(比如说,有多个开银行卡的重载方法,可以根据需要重命名为 开交行卡,开招行卡 等多种方法)。
null 的传递
当有多个默认参数时,可以考虑传递 null,当参数为 null 时,将参数设为 默认值。如:
public class Test06 {public static void apple(String a, Integer b, Integer c) {a = a == null ? "没有输入" : a;b = b == null ? 0 : b;c = c == null ? 0 : c;System.out.println(a + " " + b + " " + c + " ");}public static void main(String[] args) {apple("输入1", null, 3);apple(null,1,2);}
}
输出结果
输入1 0 3
没有输入 1 2
多参数方式
当有多个参数,且某些参数可以忽略不设置的情况下,可以考虑使用多参数方式。
友情提示:可变参数尽量写在后面,不然重载,写个同类型的数组都不行(虽然不是不能改,但写下来还是不要给以后留麻烦)
- 可选的参数类型的一致
public class Test07 {public static void apple(String color, Integer... numbers) {System.out.print(color);for (Integer number : numbers) {System.out.print(" " + number);}}public static void main(String[] args) {apple("red",1,2,3,4,5,6);// 输出:red 1 2 3 4 5 6}
}
- 可选参数类型不一致
public static void main(String[] args) {apple("red", 1, 2, 3, 4, 5, 6);// 输出:red 1 2 3 4 5 6System.out.println(" ");apple("red", "1", 2, 3, "4", "5", null, 7);}public static void apple(String color, Object... numbers) {System.out.print(color);if (numbers != null) {for (Object number : numbers) {if (number instanceof Integer || number instanceof String) {System.out.print(" " + number);}}}}
使用 Map 作为方法中的参数
当参数很多,且大部分参数都会使用默认值的情况,可以使用 Map 作为方法中的参数。
import java.util.HashMap;
import java.util.Map;public class Test08 {public static void main(String[] args) {HashMap<String, Integer> map = new HashMap<>();map.put("1", 1);map.put("2", 2);test01(map);}public static void test01(Map<String, Integer> map) {if (map != null && !map.isEmpty()) {for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());}} else {System.out.println(map);}}
}
Java编程问题top100—基础语法系列导航
Java编程问题top100—基础语法系列(一)
Java编程问题top100—基础语法系列(二)
Java编程问题top100—基础语法系列(三)
待有空再写系列四吧
能看到这的人应该没几个,加油!
如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;