lua源码,table中当key为string类型时,key值顺序不唯一

当key作为table的key值时,会根据string的hash值去映射到数组上面。

string的hash值在创建的时候会对hash复制

//lstring.c:167
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
  TString *ts;
  global_State *g = G(L);
  unsigned int h = luaS_hash(str, l, g->seed);
...
  ts = createstrobj(L, l, LUA_TSHRSTR, h);
...
  return ts;
}

//lstring.c:133
static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
  TString *ts;
  GCObject *o;
  size_t totalsize;  /* total size of TString object */
  totalsize = sizelstring(l);
  o = luaC_newobj(L, tag, totalsize);
  ts = gco2ts(o);
  ts->hash = h;
  ts->extra = 0;
  getstr(ts)[l] = '\0';  /* ending 0 */
  return ts;
}

 每次计算hash时都会用到hash种子也就是g->seed, hash种子在每次启动时都设置为当前时间

//lstate.c:295
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
...
g->seed = makeseed(L);
...
}

//lstate.c:81
static unsigned int makeseed (lua_State *L) {
...
  unsigned int h = luai_makeseed();
...
}

//lstate.c:46
#define luai_makeseed()		cast(unsigned int, time(NULL))

 

 

lua程序每次启动的g->seed都会不一样,导致相同的string,每次启动hash值都会不一样。 所以每当我们去遍历table的时候,重启之后就会发现顺序不一样。

这是lua5.3才加入的机制,在lua5.1中没有hash种子的概念。以下是lua5.1中的hsah值计算

//lua5.1 lstring.c:75
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
  GCObject *o;
  unsigned int h = cast(unsigned int, l);  /* seed */
  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */
  size_t l1;
  for (l1=l; l1>=step; l1-=step)  /* compute hash */
    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
       o != NULL;
       o = o->gch.next) {
    TString *ts = rawgco2ts(o);
    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
      /* string may be dead */
      if (isdead(G(L), o)) changewhite(o);
      return ts;
    }
  }
  return newlstr(L, str, l, h);  /* not found */
}

 

若想要每次输出都一样的话 需要单独自己按key排序,然后再去遍历table

local v = {}
local sortTable = {}
for i,_ in pairs(v) do
	if i ~= nil then 
		table.insert(sortTable, i)  
	end
end
-- 升序
table.sort(sortTable, function(a,b) return (a < b) end)
for _,sortKey in pairs(sortTable) do
	print("key:"..sortKey.." value:"..v[sortKey])
end

 

你可能感兴趣的:(库使用,算法)