如果你真的關心性能,你應該儘量避免O(n × m)
時間複雜度爲另一個字符的每個字符迭代一個字符串。因此,首先迭代一個字符串以獲得支持高效(O(1)
)查找的數據結構,然後利用此查詢迭代另一個字符串。
BitSet encountered = new BitSet();
test.chars().forEach(encountered::set);
int index = IntStream.range(0, other.length())
.filter(ix->encountered.get(other.charAt(ix)))
.findFirst().orElse(-1);
如果字符串是足夠大的,這種解決方案的O(n + m)
時間複雜度將轉向更短的執行時間。對於較小的字符串,無論如何都是無關緊要的。
如果你真的認爲,字符串是足夠大,受益於並行處理(這是非常不可能的),你可以並行執行兩個操作,以小adaptions:
BitSet encountered = CharBuffer.wrap(test).chars().parallel()
.collect(BitSet::new, BitSet::set, BitSet::or);
int index = IntStream.range(0, other.length()).parallel()
.filter(ix -> encountered.get(other.charAt(ix)))
.findFirst().orElse(-1);
第一個操作使用稍微複雜一點,並行兼容collect
現在它包含了一個不太明顯的流創建更改。
該問題描述於bug report JDK-8071477。簡單地說,由String.chars()
返回的流具有較差的分裂能力,因此並行性能差。上面的代碼將字符串包裝在CharBuffer
中,其chars()
方法返回不同的實現,具有相同的語義,但具有良好的並行性能。此解決方法應該在Java 9中過時。
或者,您可以使用IntStream.range(0, test.length()).map(test::charAt)
創建具有良好並行性能的數據流。第二個操作已經以這種方式工作。
但是,正如所說的,對於這個特定的任務,您不太可能會遇到足夠大的字符串來使並行處理變得有益。
但'e'在索引'1'處,'t'也在'other',所以它應該返回'0',對吧? – Zircon
我想知道使用並行流的性能會在這裏介紹多少。換句話說:爲什麼平行? – GhostCat
@GhostCat,我會相信通過並行檢查每個字符,複雜度會降低到第一個字符串被檢查的字符的複雜度。這是一個有一個起點的問題,並且一旦我達到能夠應用這個的更大的文本。 – relisher