問(wèn)題描述
我正在編寫 GC 友好的代碼來(lái)讀取并返回給用戶一系列 byte[]
消息.在內(nèi)部我重用相同的 ByteBuffer
這意味著我將重復(fù)返回相同的 byte[]
實(shí)例大部分時(shí)間.
我正在考慮編寫警示性 javadoc 并將其作為 迭代器
Iterator
合同,但如果他們這樣做,用戶肯定會(huì)感到驚訝 Lists.newArrayList(myIterator)
并返回一個(gè)List
在每個(gè)位置都填充了相同的 byte[]
!
問(wèn)題:對(duì)于一個(gè)可能發(fā)生變異并返回相同對(duì)象的類來(lái)實(shí)現(xiàn)Iterator
接口是不是不好的做法?p>
如果是這樣,最好的選擇是什么?不要改變/重用你的對(duì)象"是一個(gè)簡(jiǎn)單的答案.但它并沒(méi)有解決非常需要重用的情況.
如果不是,您如何證明違反最小驚訝原則?
兩個(gè)小音符:
我正在使用 Guava 的
AbstractIterator
所以 remove() 并不重要.在我的用例中,用戶是 me,并且此類的可見(jiàn)性將受到限制,但我已嘗試將這個(gè)問(wèn)題廣泛應(yīng)用于更廣泛的應(yīng)用.
更新:我接受 Louis 的回答,因?yàn)樗耐镀睌?shù)是 Keith 的 3 倍,但請(qǐng)注意,在我的用例中,我打算采用我在評(píng)論中留下的代碼基思對(duì)生產(chǎn)的回答.
EnumMap
在其 entrySet()
迭代器中基本上就是這樣做的,這會(huì)導(dǎo)致混亂、瘋狂、令人沮喪迄今為止的錯(cuò)誤.
如果我是你,我不會(huì)使用 Iterator
—— 我會(huì)編寫一個(gè)不同的 API(甚至可能與 Iterator 完全不同)并實(shí)現(xiàn)它.例如,您可以編寫一個(gè)新的 API,將 input 用作寫入消息的 ByteBuffer
,因此 API 的用戶可以控制緩沖區(qū)是否被重用.這看起來(lái)相當(dāng)直觀(用戶可以編寫明顯而干凈地重用 ByteBuffer
的代碼),而不會(huì)創(chuàng)建不必要的混亂代碼.
I'm writing GC friendly code to read and return to the user a series of byte[]
messages. Internally I reuse the same ByteBuffer
which means I'll repeatedly return the same byte[]
instance most of the time.
I'm considering writing cautionary javadoc and exposing this to the user as a Iterator<byte[]>
. AFAIK it won't violate the Iterator
contract, but the user certainly could be surprised if they do Lists.newArrayList(myIterator)
and get back a List
populated with the same byte[]
in each position!
The question: is it bad practice for a class that may mutate and return the same object to implement the Iterator
interface?
If so, what is the best alternative? "Don't mutate/reuse your objects" is an easy answer. But it doesn't address the cases when reuse is very desirable.
If not, how do you justify violating the principle of least astonishment?
Two minor notes:
I'm using Guava's
AbstractIterator
so remove() isn't really of concern.In my use case the user is me and the visibility of this class will be limited, but I've tried to ask this generally enough to apply more broadly.
Update: I'm accepting Louis' answer because it has 3x more votes than Keith's, but note that in my use case I'm planning to take the code that I left in a comment on Keith's answer to production.
EnumMap
did essentially exactly this in its entrySet()
iterator, which causes confusing, crazy, depressing bugs to this day.
If I were you, I just wouldn't use an Iterator
-- I'd write a different API (possibly quite dissimilar from Iterator, even) and implement that. For example, you might write a new API that takes as input the ByteBuffer
to write the message into, so users of the API could control whether or not the buffer gets reused. That seems reasonably intuitive (the user can write code that obviously and cleanly reuses the ByteBuffer
), without creating unnecessarily cluttered code.
這篇關(guān)于一個(gè)迭代器,它改變并返回相同的對(duì)象.不好的做法?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!