java中用print函数的输出问题。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中用print函数的输出问题。相关的知识,希望对你有一定的参考价值。

如果想在java中用printf函数输出字符串“%d”,如何实现,为什么。还有请解释一下以下代码的执行结果。
import java.util.*;
public class q
public static void main(String[] args)
Formatter f = new Formatter(System.out);
System.out.printf("%%");
System.out.printf("%");

用printf输出"%d",可以这样printf("%s","%d"); 这个是对的,本人亲测
// 定义一些变量,用来格式化输出。
05 double d = 345.678;
06 String s = "你好!";
07 int i = 1234;
08 // "%"表示进行格式化输出,"%"之后的内容为格式的定义。
09 System.out.printf("%f", d);// "f"表示格式化输出浮点数。
11 System.out.printf("%9.2f", d);// "9.2"中的9表示输出的长度,2表示小数点后的位数。
13 System.out.printf("%+9.2f", d);// "+"表示输出的数带正负号。
15 System.out.printf("%-9.4f", d);// "-"表示输出的数左对齐(默认为右对齐)。
17 System.out.printf("%+-9.3f", d);// "+-"表示输出的数带正负号且左对齐。
19 System.out.printf("%d", i);// "d"表示输出十进制整数。
21 System.out.printf("%o", i);// "o"表示输出八进制整数。
23 System.out.printf("%x", i);// "x"表示输出十六进制整数。
25 System.out.printf("%#x", i);// "#"表示输出带有十六进制标志的整数。
27 System.out.printf("%s", s);// "s"表示输出字符串。
29 System.out.printf("输出一个浮点数:%f,一个整数:%d,一个字符串:%s", d, i, s);
30 // 可以输出多个变量,注意顺序。
32 System.out.printf("字符串:%2$s,%1$d的十六进制数:%1$#x", i, s);
33 // "X$"表示第几个变量。
参考技术A java里好像是没有printf函数的,输出的格式是System.out.print(".....");
你要输出%d,只要System.out.print("%d");即可。
这段代码是有错误的,import java.util.*;这句可以去掉。
输出语言System.out.print("%%");
如果你要换行,则System.out.println("%");
如果修改后执行结果是
%%
%追问

首先,从javaSE5以后,java里面就有printf函数了
其次,加入import java.util.*一句是为了使用Formatter类,不加则报错,这里我是在做过其他试验后忘记删除这两句了
再者,我知道用System.out.println("%d");可以输出字符串“%d”,但我想知道的是如何通过System.out.printf()方法输出
最后,改程序编译不会报错,第一个输出的结果是一个百分号,第二个输出语句会出现异常UnknownFormatConversionException
我想知道为什么

追答

这里的printf函数可能跟C语言里的printf函数类似的吧。
一个%会让编译器等待你所输出数据的类型,所以有错误。
求探讨

追问

如果对java感兴趣的话,我们可以一起探讨。我的QQ号:1107948053。但是这个问题我还是不知道如何解释。刚刚看《java编程思想》上面看到相关问题,然后就试验了一下,结果就不知道如何解释了。既然是C语言风格的,那么就可以用"%d"来给一个整数占位,后面带一个整形的参数,就可以输出一个整数。而现在我想用该函数输出"%d"字符串,不知道如何操作了。我试过用转义字符“\”,还是不行……求高人……

追答

我的QQ773467459,你加我吧,你的有问题呢

参考技术B 用printf输出"%d",可以这样printf("%s","%d");本回答被提问者采纳 参考技术C System.out.println("%")您这样是输出一个“%”字符串,输出时没有任何问题的。
当然你要是输出像System.out.println(“\t")在控制台上是看不到任何效果,你可以这样尝试System.out.println(“\\t")

什么是 Java 中用于文本字符串的好的 64 位哈希函数?

【中文标题】什么是 Java 中用于文本字符串的好的 64 位哈希函数?【英文标题】:What is a good 64bit hash function in Java for textual strings? 【发布时间】:2010-12-12 05:49:23 【问题描述】:

我正在寻找一个哈希函数:

    很好地散列文本字符串(例如,很少有冲突) 用 Java 编写,应用广泛 奖励:适用于多个字段(而不是我将它们连接起来并在连接的字符串上应用哈希) 奖励:有一个 128 位版本。 奖励:不占用 CPU。

【问题讨论】:

以下链接有几种通用哈希函数的实现,它们高效且冲突最小:partow.net/programming/hashfunctions/index.html 【参考方案1】:

您为什么不使用默认String.hashCode()long 变体(其中一些非常聪明的人肯定会努力提高效率 - 更不用说已经看过这段代码的成千上万的开发人员了)?

// adapted from String.hashCode()
public static long hash(String string) 
  long h = 1125899906842597L; // prime
  int len = string.length();

  for (int i = 0; i < len; i++) 
    h = 31*h + string.charAt(i);
  
  return h;

如果您要寻找更多位,您可以使用BigInteger 编辑:

正如我在对@brianegge 答案的评论中提到的那样,超过 32 位的哈希用例并不多,而且对于超过 64 位的哈希,很可能没有一个用例:

我可以想象一个分布在数十台服务器上的巨大哈希表,可能存储数百亿个映射。对于这种情况,@brianegge 仍然有一个有效的观点:32 位允许 2^32(约 43 亿)个不同的哈希键。假设一个强大的算法,你应该仍然有相当少的碰撞。使用 64 位(18,446,744,073 亿个不同的密钥),无论您需要什么疯狂的场景,您都可以放心。不过,考虑 128 位密钥(340,282,366,920,938,463,463,374,607,431 亿个可能的密钥)的用例几乎是不可能的。

要组合多个字段的哈希值,只需进行 XOR 将一个与一个素数相乘并相加:

long hash = MyHash.hash(string1) * 31 + MyHash.hash(string2);

小素数用于避免切换值的哈希码相等,即 'foo','bar' 和 'bar','foo' 不相等,应该有不同的哈希码。 XOR 不好,因为如果两个值相等,它会返回 0。因此,'foo','foo' 和 'bar','bar' 将具有相同的哈希码。

【讨论】:

请注意,对于 好收获。较高的素数和非空起始值应该会有所帮助。 我选择了一个相当高的 64 位素数作为起始值。因此,字符串 String.hashCode 仅适用于快速计算(h * 31 已优化为 (i &lt;&lt; 5) - i),但对于避免文本哈希冲突(字符串“FB”和“Ea”冲突)。由于这个 64 位散列是相同的,它本质上具有相同的弱点。 关于 64 位和 128 位密钥的用例:也许您希望哈希作为字符串的唯一签名,以避免完全存储字符串内容。在这里,您最好 (a) 使用加密强度散列,并且 (b) 在选择散列大小时不要忘记“生日问题”(询问 wikipedia)。即使是“好”的 64 位散列也必须假定具有较低的 # 位“安全性”(比如 32 位)——因此与 BP 一起,即使对于超过 100,000 个字符串的集合,它也开始看起来很狡猾,因为它是一个独特的签名。 git 使用 160 位 SHA-1 是有原因的 :-)【参考方案2】:

今天(2018 年)的答案。 SipHash。

它会比这里的大多数答案快得多,而且质量也比所有答案都要高。

Guava 库有一个:https://google.github.io/guava/releases/23.0/api/docs/com/google/common/hash/Hashing.html#sipHash24--

【讨论】:

公认的答案(Java 的字符串散列)非常简单,以至于散列很差。 SipHash 在许多方面,由于需要大量的操作和轮次,在解释语言中过度设计、过于复杂并且速度不是很快。 MurmurHash 存在于中间,速度快,但不是特别弱。【参考方案3】:

Create an SHA-1 hash 然后屏蔽掉最低的 64 位。

【讨论】:

您甚至可以对第一个和最后一个 64 位进行 XOR。但是 SHA-1 哈希值是不是有点过头了?如果不需要加密安全哈希,那么您肯定会在要求 5 上失去一些分数;) @sfussenegger:不要尝试添加随机性。 XOR 并不总是有帮助。即使剪裁散列也会产生不可预知的结果。尝试使用几百万个测试用例或了解其背后的数学原理。否则,这种“盲目的改进”只会让事情变得更糟。 这不是增加随机性。这个想法只是保留 设计为均匀分布的 SHA-1 哈希的所有位。因此,不应该有任何意想不到的副作用 - 但第二,尽管它最终是无用的开销。剪辑也不会产生不可预测的结果 - 因为这正是例如HashMap.indexFor(int,int) 确实将哈希映射到哈希表的索引。因此,是否将 128 位散列剪裁为 64 位并不重要,因为无论如何它都会被进一步剪裁以适合散列表。 这真的取决于位的属性。以这种方式折叠散列可能会产生意外的团块,这些团块不应该在剪切时发生。但是,如果各种字符串产生非常相似的低 32 位,那么剪辑也可能会失败。这就是为什么通常最好不要在不知道其确切属性的情况下尝试“改进”现有算法。我在这里说话是因为我曾经创建了一个散列不太好的散列:) 我认为我们都至少做过一次 ;) 我很想看看这两种方法是否会导致 SHA-1 出现问题。也许有人会抽出时间来运行一个简单的测试?【参考方案4】:
long hash = string.hashCode();

是的,前 32 位将为 0,但在遇到哈希冲突问题之前,您可能会耗尽硬件资源。 String 中的 hashCode 非常高效且经过良好测试。

更新 我认为以上满足了可能工作的最简单的事情,但是,我同意@sfussenegger 扩展现有 String hashCode 的想法。

除了为您的 String 提供一个好的 hashCode 之外,您可能还需要考虑在您的实现中重新散列哈希代码。如果您的存储被其他开发人员使用,或与其他类型一起使用,这有助于分发您的密钥。比如Java的HashMap是基于2的幂的长度哈希表,所以增加了这个函数来保证低位分布充分。

    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);

【讨论】:

-1 硬件资源不是这里的问题——我没有指定如何使用哈希值,但我向你保证这不是“在哈希图中存储 n 个值”。如果我在遇到硬件问题之前处理了足够多的项目,就会发生冲突。 我可以想象一个分布在数十台服务器上的巨大哈希表,可能存储数百亿个映射。对于这种情况,@brianegge 仍然有一个有效的观点:32 位允许 2^32(约 43 亿)个不同的哈希键。假设一个强大的算法,你应该仍然有相当少的碰撞。使用 64 位(18,446,744,073 亿个不同的密钥),您几乎可以肯定地节省,无论您需要什么疯狂的场景。不过,考虑 128 位密钥(340,282,366,920,938,463,463,374,607,431 亿)的用例是完全不可能的。 这里的要点:Sun 和世界各地的几个人在过去十年中改进了这个算法。如果不投入至少一周左右的时间对琴弦的分布特性进行广泛研究,您不太可能想出一些击球手。 具有 32 位散列的散列表将在大约 65,536 个条目后开始出现问题。 32 位散列不足以用于具有数百万条目的散列表。即使是串联的 32 位哈希也不起作用;尝试过一次并经历了大幅减速【参考方案5】:

为什么不使用 CRC64 多项式。这些是相当有效和优化的,以确保所有位都被计算并分布在结果空间中。

如果你用谷歌搜索“CRC64 Java”,网上有很多可用的实现

【讨论】:

【参考方案6】:

做这样的事情:

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test 

    public static void main(String[] args) throws NoSuchAlgorithmException,
            IOException 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);

        try 
            MessageDigest md = MessageDigest.getInstance("MD5");
            SomeObject testObject = new SomeObject();

            dos.writeInt(testObject.count);
            dos.writeLong(testObject.product);
            dos.writeDouble(testObject.stdDev);
            dos.writeUTF(testObject.name);
            dos.writeChar(testObject.delimiter);
            dos.flush();

            byte[] hashBytes = md.digest(baos.toByteArray());
            BigInteger testObjectHash = new BigInteger(hashBytes);

            System.out.println("Hash " + testObjectHash);
         finally 
            dos.close();
        
    

    private static class SomeObject 
        private int count = 200;
        private long product = 1235134123l;
        private double stdDev = 12343521.456d;
        private String name = "Test Name";
        private char delimiter = '\n';
    

DataOutputStream 允许您编写原语和字符串并将它们作为字节输出。在其中包装一个ByteArrayOutputStream 可以让您写入一个字节数组,它与MessageDigest 很好地集成。您可以从here 列出的任何算法中进行选择。

最后BigInteger 将让您将输出字节转换为更易于使用的数字。 MD5 和 SHA1 算法都产生 128 位哈希,所以如果你需要 64,你可以截断。

SHA1 几乎可以很好地散列任何东西,并且很少发生冲突(它是 128 位)。这适用于 Java,但我不确定它是如何实现的。它实际上可能相当快。它适用于我的实现中的几个领域:只需将它们全部推送到DataOutputStream 就可以了。您甚至可以使用反射和注释来做到这一点(也许@HashComponent(order=1) 以显示哪些字段进入散列以及以什么顺序)。它有一个 128 位的变体,我想你会发现它使用的 CPU 没有你想象的那么多。

我已经使用这样的代码来获取庞大数据集(现在可能有数十亿个对象)的哈希值,以便能够在许多后端存储中对它们进行分片。它应该适用于您需要的任何东西。请注意,我认为您可能只想调用一次MessageDigest.getInstance(),然后从那时起调用clone():IIRC 的克隆速度要快得多。

【讨论】:

【参考方案7】:

反转字符串得到另一个 32 位哈希码,然后将两者结合起来:

String s = "astring";
long upper = ( (long) s.hashCode() ) << 32;
long lower = ( (long) s.reverse().hashCode() ) - ( (long) Integer.MIN_VALUE );
long hash64 = upper + lower;

这是伪代码; String.reverse() 方法不存在,需要以其他方式实现。

【讨论】:

【参考方案8】:

你看Apache commons lang吗?

但是对于 64 位(和 128 位),您需要一些技巧:Joshua Bloch 的《Effective Java》一书中列出的规则可帮助您轻松创建 64 位哈希(只需使用 long 而不是 int)。对于 128 位,您需要额外的技巧...

【讨论】:

Commons-lang 对于大于标准 32 位的散列完全没有帮助。它在这些方面做得很好,但除此之外就没有那么多了。【参考方案9】:

免责声明:如果您希望有效地散列单个自然语言单词,则此解决方案适用。散列较长的文本或包含非字母字符的文本效率低。

我不知道一个函数,但这里有一个可能会有所帮助的想法:

将 64 位中的 52 位用于表示字符串中存在哪些字母。例如,如果存在“a”,您将设置位[0],为“b”设置位1,为“A”设置位[26]。这样,只有包含完全相同字母集的文本才会具有相同的“签名”。

然后您可以使用剩余的 12 位对字符串长度(或它的模值)进行编码以进一步减少冲突,或使用传统的散列函数生成 12 位 hashCode。

假设您的输入是纯文本的,我可以想象这将导致很少的冲突并且计算成本低廉 (O(n))。 与迄今为止的其他解决方案不同,此方法考虑了问题域以减少冲突 - 它基于 Programming Pearls 中描述的 Anagram Detector(请参阅 here)。

【讨论】:

-1 字符串越长,您将获得越多的冲突。此外,哈希很弱,因为(假设为自然语言)大多数字符串将包含元音和频繁辅音(顺便说一句,甚至可以通过频繁辅音和元音非常可靠地猜测字符串的语言)。 @sfussenegger:OP 提到需要有良好的文本字符串,这意味着字符串长度有一些上限(例如,英语中最长的单词只有 45 个字符)。此外,OP 没有提到这需要是一个安全的哈希。 为什么这个要求意味着字符串长度的上限?这个散列函数非常弱——不管是否安全。 我怀疑这个算法会给 很多冲突 短词:rate == tearrose == sore 等等。 @sfussenegger:我同意所有你的观点。我的解决方案假设 OP 想要散列单个自然语言单词。

以上是关于java中用print函数的输出问题。的主要内容,如果未能解决你的问题,请参考以下文章

print 函数

java语言的输出函数怎么写?

时间函数

print()函数负责输出数据到屏幕上,所有数据在输出之前必须转换为字符串才能输出。“为啥错误?谢谢

Java输出和输入函数

python中print()函数的“,”与java中System.out.print()函数中的“+”