甜点的网站建设规划书朋友圈推广怎么收费
Java编程问题top100---基础语法系列(二)
- 六、如何测试一个数组是否包含指定的值?
- 简单且优雅的方法:
- 自己动手写逻辑
- 对象数组
- JDK 8 API
- JDK 9 API Set.of()
- 七、重写(Override)equlas和hashCode方法时应考虑的问题
- 理论上讲(编程语言、数学层面)
- 实践上讲
- 八、从一个多层嵌套循环中直接跳出
- 九、如何将String转换为Int
- 十、如何分割(split)string字符串
- Java编程问题top100---基础语法系列导航
感觉github上的翻译质量并没有想象中的那么好,感谢前辈的努力,但是还是得自力更生一步一步看国外文章自己动手翻译整合,码字不易,点赞支持~
萌新须知:平时写代码要老老实实判空,毕竟平时都是共同开发,不是你一个人单干,万一哪天对方改代码了,你调人家方法,返回个null给你,你也得背锅,另外不建议用assert断言,生产环境会关掉assert的。
六、如何测试一个数组是否包含指定的值?
指定数组,如:
public static final String[] VALUES = new String[]{"id", "name", "location"};
有哪些比较好的方式,判断这个数组 VALUES 是否包含值id?
简单且优雅的方法:
-
Arrays.asList(…).contains(…)
-
使用 Apache Commons Lang包中的ArrayUtils.contains(需要先引入Maven)
在pom.xml
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.11</version></dependency>
import org.apache.commons.lang3.ArrayUtils;// 测试一个数组是否包含指定的值
public class test01 {public static final String[] VALUES = new String[]{"id", "name", "location"};public static void main(String[] args) {if (ArrayUtils.contains(VALUES, "id")) {System.out.println("Contain");} else {System.out.println("Does Not Contain");}}
}
自己动手写逻辑
其实本质就是一个查找问题,即查找一个数组是否包含某个值。对于原始类型,若是无序的数组,可以直接写一个 for 循环:
import java.util.Objects;
// 无序数组public static boolean useLoop(String[] arr, String targetValue) {for (String s : arr) {// if (s.equals(targetValue)) {//不推荐这样用,以避免s为null,会不安全,改为下面这种if (Objects.equals(s,targetValue)) {return true;}}return false;}
若是有序的数组,可以考虑二分查找或者其他查找算法:
import java.util.Arrays;
// 有序数组public static boolean useArraysBinarySearch(String[] arr, String targetValue) {int a = Arrays.binarySearch(arr, targetValue);if (a >= 0) {return true;} else {return false;}}
对象数组
若数组里包含的是一个个对象,实际上比较就是引用是否相等(String 类型是判断值是否相等),本质就是比较 hashcode 和 equal 方法,可以考虑使用 List 或者 Set,如下:
public static boolean useList(String[] arr, String targetValue) {return Arrays.asList(arr).contains(targetValue);}
JDK 8 API
jdk 8及之后的jdk版本可以使用Streams
// 使用Streamspublic static void useStreams(String[] arr, String targetValue) {if (Arrays.stream(VALUES).anyMatch("id"::equals)) {System.out.println("Contain");} else {System.out.println("Does Not Contain");}}
要检查是不是int ,或double的数组或者long包含值IntStream,请分别使用 ,DoubleStream或LongStream。
举个int的例子
int[] a = {1,2,3,4};if(IntStream.of(a).anyMatch(x -> x == 4)){System.out.println("Contain");} else {System.out.println("Does Not Contain");}
JDK 9 API Set.of()
再三提示,jdk9,jdk9,jdk9。jdk 9及之后的jdk版本可以使用Set.of
jdk8的别凑热闹,不过可以知道下这个知识点,但这数据量太少,效率不高。
// 测试一个数组是否包含指定的值
public class test01 {private static final Set<String> VALUES = Set.of("id", "name", "location");public static boolean useSet(String[] arr) {if (VALUES.contains(s)) {System.out.println("Contain");} else {System.out.println("Does Not Contain");}}
}
O(1),很简洁、很漂亮~(就是开发用的JDK8用不上hh)
补充
如果数组数据量非常大,还经常使用查找的话,一般方法是O(n)线性查找,可以改用map系列。
map集合有三个常见的实现类:HashMap,TreeMap,LinkedHashMap。
TreeMap基于红黑树(一种自平衡二叉查找树)实现的,时间复杂度平均能达到O(log n)。
HashMap是基于散列表实现的,时间复杂度平均能达到O(1)。正常是O(1)到O(n)jdk1.8添加了 红黑树 是 O(log n)
TreeMap的get操作的时间复杂度是O(log(n))的,相比于HashMap的O(1)还是差不少的。
LinkedHashMap的出现就是为了平衡这些因素,能以O(1)时间复杂度查找元素,又能够保证key的有序性
为了更安全,不让修改的话,上这个Collections.unmodifiableSet,一旦修改就会报错。
/* Set<String> set = new HashSet<String>();set.add("id");set.add("name");set.add("location");Set unmodset = Collections.unmodifiableSet(set);unmodset.add("Hello");//编译运行会报错*/
七、重写(Override)equlas和hashCode方法时应考虑的问题
理论上讲(编程语言、数学层面)
equals() 定义了对象的相等关系(自反性、对称性、传递性) 。
另外,它还具有一致性(如果一个对象没有修改,那么对象的equals方法,应总是返回相同的值),此外,o.equals(null)应当总是返回false。
hashCode()也必须具备一致性的(如果equal的结果没有变,那么hashcode()也应总是返回相同的值)
总的来说,这两个方法的关系:
假如a.equals(b),那么a.hashCode() 应等于b.hashCode()
实践上讲
如果你重写了其中一个方法,那么务必重写另外一个方法
equals()和hashCode()所计算的属性集(set of fields)应当是一样的
如何更快地重写这两个方法呢?
- 使用Apache Commons Lang library中的EqualsBuilder、HashCodeBuilder
public class Person {private String name;private int age;// ...public int hashCode() {return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers// if deriving: appendSuper(super.hashCode()).append(name).append(age).toHashCode();// 我感觉IDEA直接生成的这个也不错// return Objects.hash(name, age);}public boolean equals(Object obj) {if (!(obj instanceof Person))return false;if (obj == this)return true;Person rhs = (Person) obj;return new EqualsBuilder().// if deriving: appendSuper(super.equals(obj)).append(name, rhs.name).append(age, rhs.age).isEquals();// 我感觉IDEA直接生成的这个也不错// return age == person.age && Objects.equals(name, person.name);}
}
- 代码编辑区右键,然后
(idea)选择 Generate… > equals() and hashCode()
(eclipse)选择 Source > Generate hashCode() and equals()
另外请记得
当你使用一些基于Hash的 Collection 、 Map,例如HashSet, LinkedHashSet, HashMap, Hashtable, 、WeakHashMap等。在键值对被放到集合中之后,请确保其key值所对应的hashCode()是保持不变的。比较可靠的一个办法,是保持这些key是不可变的,这也能带来不少好处
八、从一个多层嵌套循环中直接跳出
问题:
Java中如何从一个多层嵌套循环中退出,例如下面,有两个循环,break只能退出一个for循环,不能直接跳过第二个for循环
for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... break; // 这样只退出了最里的for循环 }
}}
回答:
可以用break+label的语法,例子如下
public class Test03 {public static void main(String[] args) {outerloop:for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {if (i * j > 6) {System.out.println("Breaking");break outerloop;}System.out.println(i + " " + j);}}System.out.println("Done");}
}
有一点要注意,break label的位置一定要在label代码块的内部。否则无效,语法错误。
首先在for循环前加标签,如例子中的outerloop,然后在for循环内break label(如本例的outerloop),就会跳出该label指定的for循环。
九、如何将String转换为Int
##如何将String转换为Int
有两种方式
Integer x = Integer.valueOf(str);// orint y = Integer.parseInt(str);
这两种方式有一点点不同:
valueOf
返回的是java.lang.Integer
的实例parseInt
返回的是基本数据类型 int
Short.valueOf/parseShort
,Long.valueOf/parseLong
等也是有类似差别。
另外还需注意的是,在做int类型转换时,可能会抛出NumberFormatException,因此要做好异常捕获
public class Test04 {public static void test(String[] args) {int foo;String StringThatCouldBeANumberOrNot = "26263Hello"; //will throw exceptionString StringThatCouldBeANumberOrNot2 = "26263"; //will not throw exceptiontry {foo = Integer.parseInt(StringThatCouldBeANumberOrNot);} catch (NumberFormatException e) {//Will Throw exception!//do something! anything to handle the exception.}try {foo = Integer.parseInt(StringThatCouldBeANumberOrNot2);} catch (NumberFormatException e) {//No problem this time but still it is good practice to care about exceptions.//Never trust user input :)//do something! anything to handle the exception.}}
}
十、如何分割(split)string字符串
如下所示:
String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556
需要注意的是,该方法的参数是个正则表达式
,要注意对某些字符做转码。例如.
在正则表达式中表示任意字符,因此,如果你要通过.
号做分割,需要这样写,split("\\.")
或者split(Pattern.quote("."))
如果只是为了验证字符串中是否包含某个字符,使用String的contains()
方法就行。注意该方法的参数,不是正则表达式
Java编程问题top100—基础语法系列导航
Java编程问题top100—基础语法系列(一)
Java编程问题top100—基础语法系列(二)
Java编程问题top100—基础语法系列(三) 待更新
如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;