【Java】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";

	@Test
	public 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:使用TreeMap
    public 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;
    }

    @Override
    public 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 6
        System.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—基础语法系列(三)
待有空再写系列四吧

如有错误,还请多多指教!
转载或者引用本文内容请注明来源及原作者:橘足轻重;

猜你喜欢

转载自blog.csdn.net/weixin_44510587/article/details/129259254